anomalyco/sst · error

expecting JSON key should be always a string: %T: %v

Error message

expecting JSON key should be always a string: %T: %v

What it means

While iterating the object's key tokens, UnmarshalJSON requires every key to be a JSON string. JSON technically allows only string keys, but raw/duplicate decoding or malformed input can surface a non-string token, producing this typed error with the offending Go type and value.

Source

Thrown at internal/util/kv.go:38

	// must open 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 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 {

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Fix the producer to emit RFC-8259 JSON with quoted string keys
  2. Run the payload through a strict JSON validator to find the malformed key
  3. If keys are numeric upstream, stringify them before serialization

Example fix

// before
{"123": "v"}  // generated as {123: "v"} by a JS template
// after
JSON.stringify(obj)  // yields {"123":"v"} with quoted keys
Defensive patterns

Strategy: validation

Validate before calling

var probe map[string]json.RawMessage
if err := json.Unmarshal(raw, &probe); err != nil {
    return fmt.Errorf("not an object with string keys: %w", err)
}

Type guard

func hasStringKeys(raw []byte) bool {
    var m map[string]json.RawMessage
    return json.Unmarshal(raw, &m) == nil
}

Try / catch

var kv KeyValuePairs[string]
if err := json.Unmarshal(raw, &kv); err != nil {
    if strings.Contains(err.Error(), "key should be always a string") {
        return fmt.Errorf("malformed JSON key in payload: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Input containing a non-string key token — practically seen when decoding malformed/NDJSON-like input into KeyValuePairs, e.g. '{1:"x"}' produced by a hand-built JSON string.

Common situations: Hand-rolled JSON generation in another language (JS object with numeric keys serialized oddly, or template-built JSON); a middleware or proxy mangling payloads; unquoted keys from lenient serializers (JSON5/HJSON).

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/21353e73912a2b5a. Report an issue: GitHub.