anomalyco/sst · error

expect JSON object close with '}'

Error message

expect JSON object close with '}'

What it means

After consuming all key/value pairs, UnmarshalJSON reads the closing token and requires it to be the '}' delimiter. Getting anything else means the object was truncated, an array was supplied, or trailing content is structurally invalid.

Source

Thrown at internal/util/kv.go:54

		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 {
		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)))

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Check that the full payload arrives intact — log the raw body and verify it ends with '}'
  2. Fix Content-Length/chunked issues (timeouts, proxies) causing truncation
  3. Ensure the top-level structure is an object, not an array

Example fix

// before
data := readPartial(resp.Body) // truncated stream
json.Unmarshal(data, &kv) // expect JSON object close with '}'
// after
var buf bytes.Buffer
_, err := io.Copy(&buf, resp.Body)
if err != nil { return err } // surface read errors instead
json.Unmarshal(buf.Bytes(), &kv)
Defensive patterns

Strategy: validation

Validate before calling

if !json.Valid(raw) {
    return fmt.Errorf("payload is not valid/truncated JSON")
}
trimmed := bytes.TrimSpace(raw)
if len(trimmed) > 0 && trimmed[len(trimmed)-1] != '}' {
    return fmt.Errorf("payload does not end with '}'")
}

Try / catch

var kv KeyValuePairs[string]
if err := json.Unmarshal(raw, &kv); err != nil {
    if strings.Contains(err.Error(), "expect JSON object close") {
        return fmt.Errorf("truncated response; check body transfer: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Truncated JSON body (network cut mid-response) so the decoder hits EOF where '}' was expected; decoding a JSON array; interleaved/broken streaming input.

Common situations: HTTP response body cut off by proxy timeouts; partial file reads; payload wrapped in an array at the top level after a producer refactor.

Related errors


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