{"id":"97d20684c24948b1","repo":"gohugoio/hugo","slug":"empty-deployment-target","errorCode":null,"errorMessage":"empty deployment target","messagePattern":"empty deployment target","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"deploy/deployconfig/deployConfig.go","lineNumber":154,"sourceCode":"\n// DecodeConfig creates a config from a given Hugo configuration.\nfunc DecodeConfig(cfg config.Provider) (DeployConfig, error) {\n\tdcfg := DefaultConfig\n\n\tif !cfg.IsSet(DeploymentConfigKey) {\n\t\treturn dcfg, nil\n\t}\n\tif err := mapstructure.WeakDecode(cfg.GetStringMap(DeploymentConfigKey), &dcfg); err != nil {\n\t\treturn dcfg, err\n\t}\n\n\tif dcfg.Workers <= 0 {\n\t\tdcfg.Workers = 10\n\t}\n\n\tfor _, tgt := range dcfg.Targets {\n\t\tif *tgt == (Target{}) {\n\t\t\treturn dcfg, errors.New(\"empty deployment target\")\n\t\t}\n\t\tif err := tgt.ParseIncludeExclude(); err != nil {\n\t\t\treturn dcfg, err\n\t\t}\n\t}\n\tvar err error\n\tfor _, m := range dcfg.Matchers {\n\t\tif *m == (Matcher{}) {\n\t\t\treturn dcfg, errors.New(\"empty deployment matcher\")\n\t\t}\n\t\tm.Re, err = regexp.Compile(m.Pattern)\n\t\tif err != nil {\n\t\t\treturn dcfg, fmt.Errorf(\"invalid deployment.matchers.pattern: %v\", err)\n\t\t}\n\t}\n\tfor _, o := range dcfg.Order {\n\t\tre, err := regexp.Compile(o)\n\t\tif err != nil {","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/deploy/deployconfig/deployConfig.go#L136-L172","documentation":"In `deployconfig.DecodeConfig`, after weak-decoding the `deployment` section Hugo iterates the targets and rejects any that equal the zero-value `Target{}` — meaning a target entry exists in config but carries no name, URL, or any other field. An empty target is unusable (no destination to deploy to), so config decoding fails fast.","triggerScenarios":"`hugo deploy` with a `[[deployment.targets]]` (TOML) / `deployment.targets: - ` (YAML) entry whose keys are all empty/absent or misspelled so that mapstructure decodes nothing into the struct.","commonSituations":"A stray empty `[[deployment.targets]]` table left in hugo.toml, YAML list item with wrong indentation so its keys don't nest under the target, or misspelled field names (e.g. `url =` vs `URL =` is fine, but `bucket =` decodes to nothing) leaving every field at zero value.","solutions":["Fill in the target: at minimum `name` and `url`, e.g. `name = \"prod\"` and `url = \"gs://my-bucket\"` under `[[deployment.targets]]`.","Delete any leftover empty `[[deployment.targets]]` blocks from the config.","Check YAML indentation so target keys are children of the list item; check field names against the Hugo deployment docs (name, url, cloudFrontDistributionID, googleCloudCDNOrigin, include, exclude, stripIndexHTML)."],"exampleFix":"# before\n[[deployment.targets]]\n# after\n[[deployment.targets]]\nname = \"production\"\nurl = \"gs://my-bucket\"","handlingStrategy":"validation","validationCode":"target := cfg.GetString(\"deployment.targets[0].name\")\nif strings.TrimSpace(target) == \"\" {\n    return errors.New(\"deployment target name must be non-empty\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give every `[[deployment.targets]]` entry a non-empty name and URL","When passing `--target`, ensure the flag value is non-empty and matches a configured target","Validate deployment config at startup rather than at deploy time"],"tags":["hugo","hugo-deploy","configuration","validation"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}