{"record":{"id":"189687d54439a2e5","repo":"siyuan-note/siyuan","slug":"parses-request-s-failed-s-decode","errorCode":null,"errorMessage":"Parses request [%s] failed: %s","messagePattern":"Parses request \\[(.+?)\\] failed: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/decode.go","lineNumber":27,"sourceCode":"\t\"reflect\"\n\t\"strings\"\n)\n\n// Decode 按精确的 JSON 字段名绑定请求，缺失、null 和兼容转换由字段声明控制。\nfunc (e Endpoint[Request, Data]) Decode(reader io.Reader) (request Request, err error) {\n\tif e.definition.Body == NoBody || e.definition.Body == RawBody {\n\t\treturn\n\t}\n\tif reader == nil {\n\t\treader = bytes.NewReader(nil)\n\t}\n\tif e.decodeRequest != nil {\n\t\treturn e.decodeRequest(reader)\n\t}\n\tif e.definition.Body == StructJSONBody {\n\t\terr = json.NewDecoder(reader).Decode(&request)\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"Parses request [%s] failed: %s\", e.definition.Path, err)\n\t\t}\n\t\treturn\n\t}\n\tvar fields map[string]json.RawMessage\n\terr = json.NewDecoder(reader).Decode(&fields)\n\tif err != nil {\n\t\tif e.definition.Body == LegacyOptionalBody {\n\t\t\treturn request, nil\n\t\t}\n\t\tif errors.Is(err, io.EOF) {\n\t\t\terr = errors.New(\"the request body is empty or truncated (EOF)\")\n\t\t}\n\t\treturn request, fmt.Errorf(\"Parses request [%s] failed: %s\", e.definition.Path, err)\n\t}\n\tvalue := reflect.ValueOf(&request).Elem()\n\tif value.Kind() != reflect.Struct {\n\t\treturn request, fmt.Errorf(\"request contract must be a struct\")\n\t}","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/decode.go#L9-L45","documentation":"Endpoint.Decode wraps any failure of json.Decoder.Decode when binding a StructJSONBody (or legacy-fields) request body. The wrapped Go JSON error tells you the body is not valid JSON for the declared shape — malformed syntax, wrong top-level type, trailing garbage, or an empty/truncated stream.","triggerScenarios":"POSTing to a contract endpoint with a body that fails json.Decode: invalid JSON syntax, a JSON array/string/number where a JSON object is required (legacy fields mode), an empty request body on a required-body endpoint, or a truncated body.","commonSituations":"Sending form-encoded or multipart data instead of JSON; forgetting Content-Type plus a raw body; clients sending JSON with BOM or trailing commas; empty POST bodies where the contract requires LegacyBody (not LegacyOptionalBody); proxy truncating large bodies.","solutions":["Read the wrapped %s detail — it names the exact JSON syntax/offset problem (e.g. 'unexpected end of JSON input', 'cannot unmarshal array into Go value of type map')","Send a syntactically valid JSON object body with Content-Type: application/json","Ensure the body is complete and not truncated (check Content-Length vs actual bytes, disable buffering proxies)","If the endpoint legitimately takes no body, confirm its contract declares NoBody/RawBody/LegacyOptionalBody rather than sending an empty payload"],"exampleFix":"// before\nfetch(\"/api/contract/endpoint\", {method: \"POST\", body: \"a=1&b=2\"}) // not JSON\n// after\nfetch(\"/api/contract/endpoint\", {method: \"POST\", headers: {\"Content-Type\": \"application/json\"}, body: JSON.stringify({a: 1, b: 2})})","handlingStrategy":"try-catch","validationCode":"try { JSON.parse(body); } catch (e) { console.error('client body is not valid JSON', e); }","typeGuard":null,"tryCatchPattern":"try { await callContractEndpoint(path, body) } catch (e) { if (String(e).includes('Parses request')) { console.error(`invalid JSON body for ${path}:`, e.message); } throw e; }","preventionTips":["Always send JSON.stringify'd object bodies with Content-Type: application/json","Never send form-encoded or empty bodies to StructJSONBody/LegacyBody endpoints","Parse the wrapped detail (%s) to locate the exact JSON error offset","Check for truncation when bodies pass through proxies"],"tags":["json","request-parsing","api-contract"],"backgroundTag":"json-decode-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}