{"record":{"id":"cb3679af3b4553a0","repo":"siyuan-note/siyuan","slug":"invalid-response-format-v","errorCode":null,"errorMessage":"invalid response format: %v","messagePattern":"invalid response format: (.+?)","errorType":"exception","errorClass":null,"httpStatus":500,"severity":"error","filePath":"kernel/plugin/plugin.go","lineNumber":968,"sourceCode":"\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ❌ panic: invalid memory address or nil pointer dereference\n\t\t\t// response := HttpResponse{}\n\t\t\t// if err := rt.ExportTo(responseObj, &response); err != nil {\n\t\t\t// \tdone <- &ServerHandlerResult{Error: fmt.Errorf(\"invalid response format: %v\", err)}\n\t\t\t// \treturn\n\t\t\t// }\n\n\t\t\tresultJson, marshalErr := responseObj.MarshalJSON()\n\t\t\tif marshalErr != nil {\n\t\t\t\tdone <- &handleResult{Error: marshalErr}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tresponse := HttpResponse{}\n\t\t\tif unmarshalErr := json.Unmarshal(resultJson, &response); unmarshalErr != nil {\n\t\t\t\tdone <- &handleResult{Error: fmt.Errorf(\"invalid response format: %v\", unmarshalErr)}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif raw != nil && response.Body != nil && response.Body.Raw != nil {\n\t\t\t\tresponse.Body.Raw.Data = *raw\n\t\t\t}\n\n\t\t\tdone <- &handleResult{Value: &response}\n\t\t}, rt, true, handler, handlerObj, jsRequest)\n\t\treturn\n\t}, func(_ *goja.Runtime, _ any, err error) {\n\t\tif err != nil {\n\t\t\tdone <- &handleResult{Error: err}\n\t\t}\n\t})\n\tif runErr != nil {\n\t\tdone <- &handleResult{Error: runErr}\n\t}","sourceCodeStart":950,"sourceCodeEnd":986,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/plugin.go#L950-L986","documentation":"Returned when the handler's response object cannot be unmarshalled into the kernel's HttpResponse struct. The kernel first MarshalJSON's the JS object to a string, then json.Unmarshal's it into {status, headers, body}; a type mismatch at this step yields this wrapped json error.","triggerScenarios":"Handler returns a response where status is not a number, headers is not an object/map, body is malformed, or a field that should be a string is an array/object that cannot coerce.","commonSituations":"Returning a raw fetch Response, putting a number where a string is expected (e.g. status as '200' string vs number mis-specified struct), or building the response from untyped JSON whose shape drifted.","solutions":["Match the documented HttpResponse shape exactly: status:number, headers:Record<string,string>, body:{ raw:{ mime:string, data:string|Buffer|ArrayBuffer } }.","Log JSON.stringify(response) before returning to spot the offending field.","Validate with a TS type or zod schema so shape drift fails at compile/runtime locally."],"exampleFix":"// before\nreturn { status: '200', body: { raw: { mime: 'text/plain', data: 'ok' } } };\n\n// after\nreturn { status: 200, headers: {}, body: { raw: { mime: 'text/plain', data: 'ok' } } };","handlingStrategy":"validation","validationCode":"function validResponse(r: any): boolean { return r && typeof r === 'object' && typeof r.status === 'number' && (r.headers === undefined || r.headers && typeof r.headers === 'object') && (r.body === undefined || r.body && typeof r.body === 'object'); }","typeGuard":"function isHttpResponse(r: unknown): r is { status: number; headers?: Record<string,string>; body?: { raw?: { mime: string; data: unknown } } } { if (!r || typeof r !== 'object') return false; const o = r as any; return typeof o.status === 'number'; }","tryCatchPattern":null,"preventionTips":["Match the HttpResponse struct field types exactly (status:number, headers:string map, body.raw.data:string|Buffer|ArrayBuffer).","JSON.stringify the response in dev to spot type drift.","Use a shared builder for responses so shape stays consistent."],"tags":["plugin","server","http","serialization","contract"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}