grpc-ecosystem/grpc-gateway · error
%s: %q: %w
Error message
%s: %q: %w
What it means
This error wraps a json.Decoder failure while decoding the VALUE that follows a top-level key (merge.go:199-201). The key was read successfully, but streaming the value into a json.RawMessage failed — the value is malformed (e.g. truncated string, bad number, unclosed array) or the document ends prematurely. It is prefixed with both the input name and the key name (%q) so the offending field is immediately identifiable.
Source
Thrown at openapiv3-merge/internal/merge/merge.go:201
tok, err := dec.Token()
if err != nil {
return nil, fmt.Errorf("%s: %w", in.Name, err)
}
if delim, ok := tok.(json.Delim); !ok || delim != '{' {
return nil, fmt.Errorf("%s: expected JSON object at top level", in.Name)
}
for dec.More() {
tok, err := dec.Token()
if err != nil {
return nil, fmt.Errorf("%s: %w", in.Name, err)
}
key, ok := tok.(string)
if !ok {
return nil, fmt.Errorf("%s: unexpected token %v", in.Name, tok)
}
var raw json.RawMessage
if err := dec.Decode(&raw); err != nil {
return nil, fmt.Errorf("%s: %q: %w", in.Name, key, err)
}
switch key {
case "openapi":
if err := json.Unmarshal(raw, &d.OpenAPI); err != nil {
return nil, fmt.Errorf("%s: openapi: %w", in.Name, err)
}
case "info":
d.Info = raw
case "servers":
d.Servers = raw
case "paths":
obj, err := decodeOrderedObject(raw)
if err != nil {
return nil, fmt.Errorf("%s: paths: %w", in.Name, err)
}
d.Paths = obj
case "webhooks":
obj, err := decodeOrderedObject(raw)View on GitHub (pinned to a58a4436a3)
Solutions
- Look at the key named in the error message and inspect that field's value in the input file for syntax errors.
- Run json.Valid / a linter on the input to get the exact byte offset of the malformed value.
- Escape or remove raw placeholders and unescaped quotes inside string values before merging.
- Re-export or re-download the spec if the file appears truncated mid-value.
- For generated specs, fix the generator's JSON serialization instead of post-patching the output.
Example fix
// before
"info": {"description": "uses "quotes" unescaped"} // invalid
// after
"info": {"description": "uses \"quotes\" unescaped"} Defensive patterns
Strategy: validation
Validate before calling
func preValidate(name string, data []byte) error {
if !json.Valid(data) {
return fmt.Errorf("%s: a field value is malformed; run a JSON linter for the exact offset", name)
}
return nil
} Try / catch
var syntaxErr *json.SyntaxError
if err != nil && errors.As(err, &syntaxErr) {
// err message is "<name>: \"<key>\": ..." — jump straight to that key in the file
log.Printf("fix the value of the named key; syntax error at offset %d", syntaxErr.Offset)
} Prevention
- Escape quotes and control characters inside description-like string fields.
- Never leave template placeholders ({{ }}) unresolved inside spec values.
- Detect truncation: compare downloaded size against Content-Length before merging.
- Lint every generated spec (json.Valid / Spectral) as a pre-merge CI gate.
When it happens
Trigger: Calling Merge with Input data where some top-level field's value is syntactically invalid JSON — e.g. "info": {unclosed..., a truncated paths value, or an unterminated string after "description": — causing dec.Decode(&raw) to fail for that key.
Common situations: File cut off mid-value by a failed upload/download; templating that left placeholders like {{...}} inside a value; unescaped quotes in a description string produced by a generator; an editor crash leaving a partially saved spec.
Related errors
AI-assisted analysis of grpc-ecosystem/grpc-gateway@a58a4436a3 (2026-09-02).
Data as JSON: /api/errors/fe2517f13f2e9060.
Report an issue: GitHub.