gohugoio/hugo · error
version name cannot be empty
Error message
version name cannot be empty
What it means
Thrown by VersionsInternal.init in hugolib/versions/versions.go:165 when the versionConfigs map contains the empty-string key. Hugo's content-versions feature keys each version by name; an empty key is rejected before semver parsing/sorting.
Solutions
- Inspect the [versions] section of hugo.toml and remove/rename any [versions.""] entry.
- Give every version a non-empty identifier, e.g. [versions.v1] and [versions.v2].
- Run hugo config to print the resolved versions map and locate the empty key.
Example fix
// before [versions] [versions.""] weight = 1 // after [versions.v1] weight = 1
Defensive patterns
Strategy: validation
Validate before calling
// Before building config, reject empty version keys.
for k := range versionConfigs {
if k == "" { return errors.New("remove empty version key") }
} Prevention
- Validate the [versions] table with hugo config before building.
- Never emit a [versions.""] entry from config generators.
- Treat an empty version key as a config-generation bug.
When it happens
Trigger: Configuring [versions] with an empty-key sub-table (e.g. [versions.""]), or programmatically building a versions config map containing the "" key. init runs during site matrix construction.
Common situations: Malformed TOML/YAML under [versions], a config template that emits a blank version key, or a typo producing a quoted-empty key. A default version ("v1.0.0") is auto-added when none are configured, so this fires only on an explicit empty key.
Related errors
- version name is invalid
- config needs a filename
- empty related config provided
- failed to decode languages config
- failed to decode options for resource
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/9254f5c7e01d7c71.
Report an issue: GitHub.
Appendix: source
Thrown at hugolib/versions/versions.go:165
const defaultContentVersionFallback = "v1.0.0"
func (r *VersionsInternal) init(defaultContentVersion string) error {
if r.versionConfigs == nil {
r.versionConfigs = make(map[string]VersionConfig)
}
defaultContentVersionProvided := defaultContentVersion != ""
if len(r.versionConfigs) == 0 {
if defaultContentVersion == "" {
defaultContentVersion = defaultContentVersionFallback
}
// Add a default version.
r.versionConfigs[defaultContentVersion] = VersionConfig{}
}
var defaultSeen bool
for k, v := range r.versionConfigs {
if k == "" {
return errors.New("version name cannot be empty")
}
if err := paths.ValidateIdentifier(k); err != nil {
return fmt.Errorf("version name %q is invalid: %s", k, err)
}
var isDefault bool
if k == defaultContentVersion {
isDefault = true
defaultSeen = true
}
// Ignore error, this may not be a semver version.
parsedVersion, _ := version.ParseVersion(k)
r.Sorted = append(r.Sorted, VersionInternal{Name: k, parsedVersion: parsedVersion, Default: isDefault, VersionConfig: v})
}
// Sort by weight if set, then semver descending.View on GitHub (pinned to 52c9bd7908)