{"id":"6756604042d0f1b5","repo":"gohugoio/hugo","slug":"language-name-q-is-invalid-s","errorCode":null,"errorMessage":"language name %q is invalid: %s","messagePattern":"language name %q is invalid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"langs/config.go","lineNumber":159,"sourceCode":"\t}\n\n\tvar (\n\t\tdefaultSeen bool\n\t\tenIdx       int = -1\n\t)\n\tfor k, v := range ls.LanguageConfigs {\n\t\tif !v.Disabled && slices.Contains(disabledLanguages, k) {\n\t\t\t// This language is disabled.\n\t\t\tv.Disabled = true\n\t\t\tls.LanguageConfigs[k] = v\n\t\t}\n\n\t\tif k == \"\" {\n\t\t\treturn \"\", errors.New(\"language name cannot be empty\")\n\t\t}\n\n\t\tif err := paths.ValidateIdentifier(k); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"language name %q is invalid: %s\", k, err)\n\t\t}\n\n\t\tvar isDefault bool\n\t\tif k == defaultContentLanguage {\n\t\t\tisDefault = true\n\t\t\tdefaultSeen = true\n\t\t}\n\n\t\tif isDefault && v.Disabled {\n\t\t\treturn \"\", fmt.Errorf(\"default language %q is disabled\", k)\n\t\t}\n\n\t\tif !v.Disabled {\n\t\t\tls.Sorted = append(ls.Sorted, LanguageInternal{Name: k, Default: isDefault, LanguageConfig: v})\n\t\t}\n\t}\n\n\t// Sort by weight if set, then by name.","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/langs/config.go#L141-L177","documentation":"Raised in LanguagesInternal.init (langs/config.go:159) when a language key fails paths.ValidateIdentifier. Language names are used as URL path segments and internal identifiers, so they must be valid identifiers (roughly letters/digits/hyphen/underscore, no spaces or reserved characters); the wrapped error explains which rule was violated.","triggerScenarios":"A `languages` map key containing invalid characters — spaces, slashes, dots, or other characters rejected by ValidateIdentifier, e.g. `languages.\"en US\"` or `languages.\"fr/ca\"`.","commonSituations":"Using full locale display names or BCP47 variants with unexpected punctuation as language keys, copy-paste from locale lists, or generated configs interpolating unsanitized values.","solutions":["Rename the language key to a valid identifier such as `en`, `en-us`, or `zh-cn`.","Put the human-readable name in `label` (formerly languageName) instead of the key.","Set `languageCode` for the precise BCP47 code while keeping the key simple."],"exampleFix":"# before\n[languages.\"en US\"]\nlabel = \"English\"\n# after\n[languages.en-us]\nlabel = \"English\"\nlanguageCode = \"en-US\"","handlingStrategy":"validation","validationCode":"import \"golang.org/x/text/language\"\n// Validate each language key parses as a BCP 47 tag before load\nfor lang := range cfg.GetStringMap(\"languages\") {\n    if _, err := language.Parse(lang); err != nil {\n        return fmt.Errorf(\"invalid language key %q: %w\", lang, err)\n    }\n}","typeGuard":"func isValidLangTag(s string) bool {\n    _, err := language.Parse(s)\n    return err == nil\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"is invalid\") {\n    return fmt.Errorf(\"use a valid BCP 47 code (e.g. \\\"en\\\", \\\"pt-br\\\", \\\"zh-hans\\\") as the language key: %w\", err)\n}","preventionTips":["Use standard BCP 47 codes as [languages] keys (en, fr, pt-br)","Don't use display names (\"English\") or arbitrary strings as language keys","Validate keys with golang.org/x/text/language.Parse in any config generator"],"tags":["hugo","config","multilingual","validation"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}