anomalyco/sst · error
expect end of JSON object but got more token: %T: %v or err:
Error message
expect end of JSON object but got more token: %T: %v or err: %v
What it means
Once the closing '}' is consumed, UnmarshalJSON requires the decoder to be at EOF. If another token remains (or a non-EOF error exists), it reports 'expect end of JSON object but got more token'. This rejects concatenated or trailing garbage after the object.
Source
Thrown at internal/util/kv.go:62
}
*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 {
return fmt.Errorf("expect end of JSON object but got more token: %T: %v or err: %v", t, t, err)
}
return nil
}
func (p KeyValuePairs[T]) MarshalJSON() ([]byte, error) {
buf := &bytes.Buffer{}
buf.Write([]byte{'{'})
for i, KeyValuePair := range p {
buf.WriteString(fmt.Sprintf("%q:", fmt.Sprintf("%v", KeyValuePair.Key)))
encoder := json.NewEncoder(buf)
encoder.SetEscapeHTML(false)
err := encoder.Encode(KeyValuePair.Value)
if err != nil {
return nil, err
}
if i < len(p)-1 {
buf.Write([]byte{','})View on GitHub (pinned to a0bd20f762)
Solutions
- Feed exactly one JSON document per Unmarshal call — split NDJSON by lines first
- Trim trailing whitespace/garbage from the payload
- Use a json.Decoder loop over multiple documents if the stream intentionally holds several objects
Example fix
// before
dec := json.NewDecoder(conn)
var kv KeyValuePairs[string]
json.Unmarshal(buf, &kv) // buf has two concatenated objects
// after
lines := bytes.Split(buf, []byte("\n"))
for _, l := range lines {
var kv KeyValuePairs[string]
json.Unmarshal(l, &kv)
} Defensive patterns
Strategy: validation
Validate before calling
dec := json.NewDecoder(bytes.NewReader(raw))
if err := dec.Decode(&json.RawMessage{}); err != nil {
return err
}
if dec.More() {
return fmt.Errorf("trailing data after first JSON document")
} Try / catch
var kv KeyValuePairs[string]
if err := json.Unmarshal(raw, &kv); err != nil {
if strings.Contains(err.Error(), "expect end of JSON object") {
return fmt.Errorf("multiple/trailing JSON documents; split NDJSON first")
}
return err
} Prevention
- Split NDJSON/concatenated JSON into individual documents before unmarshal
- Trim trailing whitespace and garbage from external input
- Use json.Decoder in a loop when streams intentionally contain multiple documents
When it happens
Trigger: Input with trailing data after the object, e.g. '{"a":1}{"b":2}' (JSON concatenation/streaming), trailing commas parsed oddly, or appended newline-separated records.
Common situations: NDJSON files fed to json.Unmarshal one blob at a time; log collectors concatenating JSON docs; copy-paste errors leaving stray characters after the object.
Related errors
- expect JSON object open with '{'
- expecting JSON key should be always a string: %T: %v
- JSON value can't be decoded: %T: %v
- expect JSON object close with '}'
- panic(err)
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/81cdd25be310d623.
Report an issue: GitHub.