anomalyco/sst · error
JSON value can't be decoded: %T: %v
Error message
JSON value can't be decoded: %T: %v
What it means
After reading each key, UnmarshalJSON decodes the value into T; if the value does not match T (or is malformed) it wraps the failure as 'JSON value can't be decoded: <type>: <value>'. It tells you which key's value failed to fit the declared generic type.
Source
Thrown at internal/util/kv.go:43
}
if delim, ok := t.(json.Delim); !ok || delim != '{' {
return fmt.Errorf("expect JSON object open with '{'")
}
for dec.More() {
t, err = dec.Token()
if err != nil {
return err
}
key, ok := t.(string)
if !ok {
return fmt.Errorf("expecting JSON key should be always a string: %T: %v", t, t)
}
var value T
err = dec.Decode(&value)
if err != nil {
return fmt.Errorf("JSON value can't be decoded: %T: %v", value, value)
}
*p = append(*p, KeyValuePair[T]{Key: key, Value: value})
}
// must end with a delim token '}'
t, err = dec.Token()
if err != nil {
return err
}
if delim, ok := t.(json.Delim); !ok || delim != '}' {
return fmt.Errorf("expect JSON object close with '}'")
}
if err != nil {
return err
}
t, err = dec.Token()
if err != io.EOF {View on GitHub (pinned to a0bd20f762)
Solutions
- Change T to match the actual value type (e.g. KeyValuePairs[string] or KeyValuePairs[any])
- Fix the producer to emit values of type T
- Use json.Number/any as T and convert manually after decode
Example fix
// before
var kv KeyValuePairs[int]
json.Unmarshal([]byte(`{"port":"8080"}`), &kv)
// after
var kv KeyValuePairs[string]
json.Unmarshal([]byte(`{"port":"8080"}`), &kv)
port, _ := strconv.Atoi(kv[0].Value) Defensive patterns
Strategy: type-guard
Validate before calling
var probe map[string]any
if err := json.Unmarshal(raw, &probe); err != nil {
return err
}
for k, v := range probe {
if _, ok := v.(string); !ok {
return fmt.Errorf("key %q value is %T, want string", k, v)
}
} Type guard
func allValuesOfType[T any](raw []byte) bool {
var probe map[string]T
return json.Unmarshal(raw, &probe) == nil
} Try / catch
var kv KeyValuePairs[string]
if err := json.Unmarshal(raw, &kv); err != nil {
if strings.Contains(err.Error(), "can't be decoded") {
return fmt.Errorf("value type mismatch; use a looser T like any or json.Number")
}
return err
} Prevention
- Match T to the real payload value type; prefer any/json.Number for heterogeneous data
- Document the expected value type in the API contract
- Add unit tests round-tripping representative payloads
When it happens
Trigger: Decoding an object whose values are, say, strings into KeyValuePairs[int] (e.g. {"port": "8080"} into int), or a value being null/nested where T is a scalar.
Common situations: Environment/config files where values are quoted strings but the Go type expects numbers; schema drift where an API started returning objects instead of scalars; a null sneaking into a field typed as non-pointer T.
Related errors
- expect JSON object open with '{'
- expecting JSON key should be always a string: %T: %v
- expect JSON object close with '}'
- expect end of JSON object but got more token: %T: %v or err:
- panic(err)
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/6dcc4279c161b148.
Report an issue: GitHub.