gohugoio/hugo · error
unable to convert value of type
Error message
unable to convert value of type %q to %q
What it means
Returned by hreflect's errConvert helper when ToInt64E/ToFloat64E/ToStringE cannot convert a reflect.Value to the requested target type. ConvertIfPossible only handles int/uint/float/string cross-conversions losslessly; any other kind (struct, slice, map, bool, complex, channel, func) yields this error naming both the source type and the target kind.
Solutions
- Pre-check the reflect.Kind before calling; handle non-convertible kinds explicitly.
- For uint64 sources, guard against overflow (> MaxInt64) before converting to int64.
- If you need a string of a struct, marshal to JSON instead of relying on ToStringE.
Example fix
// before
i, err := hreflect.ToInt64E(reflect.ValueOf(myStruct))
// after
if v.Kind() == reflect.Struct {
b,_ := json.Marshal(v.Interface())
// use string(b)
} else {
i, err := hreflect.ToInt64E(v)
} Defensive patterns
Strategy: type-guard
Validate before calling
func convertibleTo(rv reflect.Value, kind reflect.Kind) bool {
switch rv.Kind() {
case reflect.Bool, reflect.String, reflect.Struct, reflect.Map, reflect.Slice, reflect.Array, reflect.Chan, reflect.Func: return false
}
return true
} Type guard
func isNumericOrString(rv reflect.Value) bool {
k := rv.Kind()
return hreflect.IsInt(k) || hreflect.IsUint(k) || hreflect.IsFloat(k) || hreflect.IsString(k)
} Prevention
- Marshal structs to JSON for string conversion instead of reflection.
- Guard uint64 → int64 against overflow (> math.MaxInt64).
- Check Kind before invoking ToInt64E/ToFloat64E/ToStringE.
When it happens
Trigger: Calling hreflect.ToInt64E/ToFloat64E/ToStringE with a reflect.Value whose Kind is bool, struct, slice, map, or a numeric that would overflow the target (e.g. uint64 > MaxInt64).
Common situations: Reflection-based template helpers trying to stringify or numerify a structured value from frontmatter, or converting a large unsigned integer produced by the YAML decoder (see Issue 14079) into an int64 that overflows.
Related errors
- argument must be a slice
- can't apply over
- can't iterate over %T
- cannot append slice of
- is neither a struct field, a method nor a map element of…
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/83f2d38def6b3616.
Report an issue: GitHub.
Appendix: source
Thrown at common/hreflect/convert.go:88
func ToStringValueE(v reflect.Value) (reflect.Value, error) {
if v, ok := ConvertIfPossible(v, typeString); ok {
return v, nil
}
return reflect.Value{}, errConvert(v, "string")
}
// ToString converts v to string if possible, panicking if not.
func ToString(v reflect.Value) string {
vv, err := ToStringE(v)
if err != nil {
panic(err)
}
return vv
}
func errConvert(v reflect.Value, s string) error {
return fmt.Errorf("unable to convert value of type %q to %q", v.Type().String(), s)
}
// ConvertIfPossible tries to convert val to typ if possible.
// This is currently only implemented for int kinds,
// added to handle the move to a new YAML library which produces uint64 for unsigned integers.
// We can expand on this later if needed.
// This conversion is lossless.
// See Issue 14079.
func ConvertIfPossible(val reflect.Value, typ reflect.Type) (reflect.Value, bool) {
switch val.Kind() {
case reflect.Pointer, reflect.Interface:
if val.IsNil() {
// Return typ's zero value.
return reflect.Zero(typ), true
}
val = val.Elem()
}
View on GitHub (pinned to 52c9bd7908)