gohugoio/hugo · error
value is nil; should be of type %s
Error message
value is nil; should be of type %s
What it means
Thrown by prepareArg (used by doIndex for map indexing) when the supplied index value is reflect.Invalid (untyped nil) and the map's key type is not nillable (canBeNil returns false for non-chan/func/interface/map/pointer/slice kinds). A nil index only makes sense for nillable key types; for concrete key types like int or string it is an error naming the expected type via %s.
Source
Thrown at tpl/collections/index.go:126
}
case reflect.Invalid:
// the loop holds invariant: v.IsValid()
panic("unreachable")
default:
return nil, fmt.Errorf("can't index item of type %s", v.Type())
}
}
return v.Interface(), nil
}
// prepareArg checks if value can be used as an argument of type argType, and
// converts an invalid value to appropriate zero if possible.
//
// Copied from Go stdlib src/text/template/funcs.go.
func prepareArg(value reflect.Value, argType reflect.Type) (reflect.Value, error) {
if !value.IsValid() {
if !canBeNil(argType) {
return reflect.Value{}, fmt.Errorf("value is nil; should be of type %s", argType)
}
value = reflect.Zero(argType)
}
if !value.Type().AssignableTo(argType) {
return reflect.Value{}, fmt.Errorf("value has type %s; should be %s", value.Type(), argType)
}
return value, nil
}
// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
//
// Copied from Go stdlib src/text/template/exec.go.
func canBeNil(typ reflect.Type) bool {
switch typ.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice:
return true
}
return falseView on GitHub (pinned to 52c9bd7908)
Solutions
- Default the key before indexing: `{{ $k := default "fallback" $maybeNil }}{{ index $m $k }}`.
- Guard with isset/with: `{{ with $maybeNil }}{{ index $m . }}{{ end }}`.
- Use a map with a pointer/interface key type if nil keys are legitimate.
- Ensure partial callers always pass the key argument.
Example fix
// before
{{ index $stringMap $missingKey }}
// after
{{ with $missingKey }}{{ index $stringMap . }}{{ else }}{{ index $stringMap "default" }}{{ end }} Defensive patterns
Strategy: validation
Validate before calling
func nonNilMapKey(mapV reflect.Value, key any) (reflect.Value, error) {
if key == nil || !reflect.ValueOf(key).IsValid() {
kt := mapV.Type().Key()
switch kt.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice:
return reflect.Zero(kt), nil
default:
return reflect.Value{}, fmt.Errorf("nil key invalid for map key type %s", kt)
}
}
return reflect.ValueOf(key), nil
} Type guard
func canKeyBeNil(kt reflect.Type) bool {
switch kt.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice:
return true
}
return false
} Prevention
- Default optional keys before indexing maps.
- Guard with `with`/isset when a key may be nil.
- Require partial callers to always pass required keys.
- Use a nillable key type only if nil keys are legitimate.
When it happens
Trigger: Calling `{{ index $intKeyedMap nil }}` where the map is `map[int]...`, or `{{ index $stringKeyedMap $missing }}` where $missing resolved to untyped nil. prepareArg receives an invalid reflect.Value and the map key type (e.g. string, int) cannot hold nil.
Common situations: A template variable that was never set (defaults to nil) is used as a map key, or optional front matter is nil and passed straight through. Common with optional params in partials where a key may be absent.
Related errors
- value has type %s; should be %s
- index of type %T with args %v failed: %s
- cannot index slice/array with type %s
- can't index item of type %s
- cannot index slice/array with nil
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/ca9740ddc0dd019a.
Report an issue: GitHub.