gohugoio/hugo · error

value is nil; should be of type %s

Error message

value is nil; should be of type %s

What it means

Returned by prepareArg when the argument value is invalid (reflect zero = nil/absent) but the target parameter type cannot hold nil (not chan/func/interface/map/pointer/slice). This is raised while coercing template arguments to a func/method/Map key type, e.g. calling a func whose param is int but the template passed an unset variable. The %s is the expected type.

Source

Thrown at tpl/internal/go_templates/texttemplate/funcs.go:150

	if tmpl != nil && tmpl.common != nil {
		tmpl.muFuncs.RLock()
		defer tmpl.muFuncs.RUnlock()
		if fn := tmpl.execFuncs[name]; fn.IsValid() {
			return fn, false, true
		}
	}
	if fn := builtinFuncs()[name]; fn.IsValid() {
		return fn, true, true
	}
	return reflect.Value{}, false, false
}

// prepareArg checks if value can be used as an argument of type argType, and
// converts an invalid value to appropriate zero if possible.
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 value, nil
	}
	if intLike(value.Kind()) && intLike(argType.Kind()) && value.Type().ConvertibleTo(argType) {
		value = value.Convert(argType)
		return value, nil
	}
	return reflect.Value{}, fmt.Errorf("value has type %s; should be %s", value.Type(), argType)
}

func intLike(typ reflect.Kind) bool {
	switch typ {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return true
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:

View on GitHub (pinned to 52c9bd7908)

Solutions

  1. Make the func parameter an interface{} or a nillable type if nil is a valid input.
  2. Guard in the template with {{if .Field}}...{{end}} before calling the func.
  3. Provide a non-nil default/zero value for the data before rendering.
  4. Widen the func signature to accept and explicitly handle nil.

Example fix

// before
// func: func(n int) string
{{ lower .Missing }} // .Missing is nil -> error

// after
// func: func(v any) string
{{ if .Missing }}{{ lower .Missing }}{{ end }}
Defensive patterns

Strategy: type-guard

Validate before calling

func safeCallFunc(fn func(int) string, v any) (string, error) {
    if v == nil {
        return "", fmt.Errorf("argument is nil")
    }
    n, ok := v.(int)
    if !ok {
        return "", fmt.Errorf("argument not int: %T", v)
    }
    return fn(n), nil
}

Type guard

func isNonNilAssignable(v any, t reflect.Type) bool {
    if v == nil { return false }
    rv := reflect.ValueOf(v)
    return rv.IsValid() && rv.Type().AssignableTo(t)
}

Try / catch

if err := t.Execute(w, data); err != nil {
    if strings.Contains(err.Error(), "value is nil; should be of type") {
        // provide defaults for nil fields and retry once
        data = withDefaults(data)
        err = t.Execute(w, data)
    }
}

Prevention

When it happens

Trigger: Passing nil to a template function/method/index whose parameter type is non-nillable (int, string, struct, array); an unset pipeline variable ($x never assigned) flowing into a typed arg; a missing map key passed to a typed func.

Common situations: Template references a nil context field that feeds a typed func; a partial invoked without expected data; a FuncMap func with a concrete (non-interface) param type receiving a nil dot.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/d31a869f30ce33d3. Report an issue: GitHub.