gohugoio/hugo · error
value has type %s; should be %s
Error message
value has type %s; should be %s
What it means
Returned by prepareArg when the argument value is valid but not assignable to the target parameter type and not an int-like convertible value. This is the general type-mismatch path during argument coercion (func calls, map key indexing, the call builtin). The first %s is the value's actual type; the second %s is the expected type.
Source
Thrown at tpl/internal/go_templates/texttemplate/funcs.go:161
}
// 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:
return true
}
return false
}
// indexArg checks if a reflect.Value can be used as an index, and converts it to int if possible.
func indexArg(index reflect.Value, cap int) (int, error) {
var x int64
switch index.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
x = index.Int()View on GitHub (pinned to 52c9bd7908)
Solutions
- Align the template-supplied value's type with the func/map parameter type.
- Widen the func parameter to interface{} and convert inside, returning an error on mismatch.
- Convert the value in the template via a helper func before passing it.
- Add type assertions/conversions in the data preparation layer.
Example fix
// before
// func: func(n int) string ; data gives .Count as string
{{ inc .Count }} // type mismatch
// after
// func: func(v any) (string, error) that parses/converts
{{ inc .Count }}
// or ensure .Count is int in the data model before render Defensive patterns
Strategy: type-guard
Validate before calling
func coerce(v any, t reflect.Type) (any, error) {
rv := reflect.ValueOf(v)
if !rv.IsValid() { return nil, fmt.Errorf("nil value") }
if !rv.Type().AssignableTo(t) {
return nil, fmt.Errorf("%T not assignable to %s", v, t)
}
return v, nil
} Type guard
func matchesType(v any, t reflect.Type) bool {
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 has type") {
// normalize data types (e.g. strconv) and retry
data = normalizeTypes(data)
err = t.Execute(w, data)
}
} Prevention
- Align template data types with func parameter types.
- Use interface{} params and convert inside the func.
- Unit-test funcs against the exact types templates supply.
When it happens
Trigger: Passing a string where an int is expected (or vice versa) to a typed template func/method; indexing a map whose key type doesn't match the provided key; calling via the call builtin with mismatched arg types.
Common situations: FuncMap func with a concrete param type receiving a differently-typed template value; map key typed as int but template passes a string from URL params; refactoring a struct field's type without updating templates.
Related errors
- invalid function signature for %s: second return value shoul
- function %s has %d return values; should be 1 or 2
- value is nil; should be of type %s
- cannot index slice/array with type %s
- cannot index slice/array with nil
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/ad8e1f4bf378d19e.
Report an issue: GitHub.