anomalyco/sst · error
expect JSON object open with '{'
Error message
expect JSON object open with '{' What it means
KeyValuePairs.UnmarshalJSON parses a JSON object incrementally with json.Decoder tokens. If the first token is not the '{' delimiter — i.e. the input is an array, string, number, or malformed — it returns this error. It enforces that the serialized form of KeyValuePairs is a JSON object.
Source
Thrown at internal/util/kv.go:27
type KeyValuePair[T any] struct {
Key string
Value T
}
type KeyValuePairs[T any] []KeyValuePair[T]
func (p *KeyValuePairs[T]) UnmarshalJSON(data []byte) error {
*p = make(KeyValuePairs[T], 0)
dec := json.NewDecoder(bytes.NewReader(data))
dec.UseNumber()
// 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})View on GitHub (pinned to a0bd20f762)
Solutions
- Ensure the input is a JSON object like {"key":"value"}, not an array
- Check the producer/API contract and fix the payload shape
- Validate JSON with a parser before unmarshaling to catch truncation
Example fix
// before
var kv KeyValuePairs[string]
json.Unmarshal([]byte(`[{"k":"v"}]`), &kv)
// after
var kv KeyValuePairs[string]
json.Unmarshal([]byte(`{"k":"v"}`), &kv) Defensive patterns
Strategy: validation
Validate before calling
var probe any
if err := json.Unmarshal(raw, &probe); err != nil {
return fmt.Errorf("invalid JSON: %w", err)
}
if m, ok := probe.(map[string]any); !ok {
return fmt.Errorf("expected JSON object, got %T", probe)
} Type guard
func isJSONObject(raw []byte) bool {
var m map[string]any
return json.Unmarshal(raw, &m) == nil && m != nil
} Try / catch
var kv KeyValuePairs[string]
if err := json.Unmarshal(raw, &kv); err != nil {
if strings.Contains(err.Error(), "expect JSON object open") {
return fmt.Errorf("payload must be a JSON object: %w", err)
}
return err
} Prevention
- Validate payloads against a JSON schema before unmarshal
- Log the raw body when decoding fails to spot shape mismatches
- Keep producers and consumers on a shared contract/schema definition
When it happens
Trigger: Unmarshaling a JSON array (e.g. '[{"k":"v"}]'), a bare string/number, or empty/garbage input into a KeyValuePairs[T] field.
Common situations: API payload changed shape from object to array; feeding a JSON lines file into json.Unmarshal; a producer wrote an array of pairs while the consumer expects an object; corrupted/truncated JSON body.
Related errors
- expecting JSON key should be always a string: %T: %v
- JSON value can't be decoded: %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/b78089ed6fdffe0c.
Report an issue: GitHub.