{"record":{"id":"6783f5c0eeedfe71","repo":"gohugoio/hugo","slug":"role-name-cannot-be-empty","errorCode":null,"errorMessage":"role name cannot be empty","messagePattern":"role name cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hugolib/roles/roles.go","lineNumber":150,"sourceCode":"const defaultContentRoleFallback = \"guest\"\n\nfunc (r *RolesInternal) init(defaultContentRole string) (string, error) {\n\tif r.roleConfigs == nil {\n\t\tr.roleConfigs = make(map[string]RoleConfig)\n\t}\n\tdefaultContentRoleProvided := defaultContentRole != \"\"\n\tif len(r.roleConfigs) == 0 {\n\t\t// Add a default role.\n\t\tif defaultContentRole == \"\" {\n\t\t\tdefaultContentRole = defaultContentRoleFallback\n\t\t}\n\t\tr.roleConfigs[defaultContentRole] = RoleConfig{}\n\t}\n\n\tvar defaultSeen bool\n\tfor k, v := range r.roleConfigs {\n\t\tif k == \"\" {\n\t\t\treturn \"\", errors.New(\"role name cannot be empty\")\n\t\t}\n\n\t\tif err := paths.ValidateIdentifier(k); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"role name %q is invalid: %s\", k, err)\n\t\t}\n\n\t\tvar isDefault bool\n\t\tif k == defaultContentRole {\n\t\t\tisDefault = true\n\t\t\tdefaultSeen = true\n\t\t}\n\n\t\tr.Sorted = append(r.Sorted, RoleInternal{Name: k, Default: isDefault, RoleConfig: v})\n\t}\n\n\t// Sort by weight if set, then by name.\n\tsort.SliceStable(r.Sorted, func(i, j int) bool {\n\t\tri, rj := r.Sorted[i], r.Sorted[j]","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/hugolib/roles/roles.go#L132-L168","documentation":"Thrown by RolesInternal.init in hugolib/roles/roles.go:150 when iterating the roleConfigs map and a key is the empty string. Hugo's content-roles feature (multi-audience rendering) keys each role by name, so an empty key is rejected before sorting/validation.","triggerScenarios":"Configuring [roles] with an empty-key sub-table in TOML (e.g. [roles.\"\"]), or programmatically building a roles config map containing the \"\" key. The init runs during site matrix construction in site.go.","commonSituations":"Malformed TOML/YAML config under [roles], a copy-paste that produced an empty quoted key, or a config generator that emits a blank role entry. A default role (\"guest\") is added automatically when no roles are configured, so this only fires on an explicit empty key.","solutions":["Inspect the [roles] section of hugo.toml and remove or rename any [roles.\"\"] entry.","Give every role a non-empty identifier, e.g. [roles.member] and [roles.admin].","Run hugo config to print the resolved roles map and locate the empty key."],"exampleFix":"// before\n[roles]\n[roles.\"\"]\nweight = 1\n// after\n[roles.member]\nweight = 1","handlingStrategy":"validation","validationCode":"// Before building config, reject empty role keys.\nfor k := range roleConfigs {\n    if k == \"\" { return errors.New(\"remove empty role key\") }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate the [roles] table with hugo config before building.","Never emit a [roles.\"\"] entry from config generators.","Treat an empty role key as a config-generation bug."],"tags":["config","roles","validation"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}