siyuan-note/siyuan · error
invalid response format: %v
Error message
invalid response format: %v
What it means
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.
Source
Thrown at kernel/plugin/plugin.go:968
}
}
// ❌ panic: invalid memory address or nil pointer dereference
// response := HttpResponse{}
// if err := rt.ExportTo(responseObj, &response); err != nil {
// done <- &ServerHandlerResult{Error: fmt.Errorf("invalid response format: %v", err)}
// return
// }
resultJson, marshalErr := responseObj.MarshalJSON()
if marshalErr != nil {
done <- &handleResult{Error: marshalErr}
return
}
response := HttpResponse{}
if unmarshalErr := json.Unmarshal(resultJson, &response); unmarshalErr != nil {
done <- &handleResult{Error: fmt.Errorf("invalid response format: %v", unmarshalErr)}
return
}
if raw != nil && response.Body != nil && response.Body.Raw != nil {
response.Body.Raw.Data = *raw
}
done <- &handleResult{Value: &response}
}, rt, true, handler, handlerObj, jsRequest)
return
}, func(_ *goja.Runtime, _ any, err error) {
if err != nil {
done <- &handleResult{Error: err}
}
})
if runErr != nil {
done <- &handleResult{Error: runErr}
}View on GitHub (pinned to 251596fc0d)
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.
Example fix
// before
return { status: '200', body: { raw: { mime: 'text/plain', data: 'ok' } } };
// after
return { status: 200, headers: {}, body: { raw: { mime: 'text/plain', data: 'ok' } } }; Defensive patterns
Strategy: validation
Validate before calling
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'); } Type guard
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'; } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- handler did not return an object
- event.data is required
- failed to serialize inputSchema: %v
- failed to serialize config.%s: %v
- failed to convert request value to object
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/cb3679af3b4553a0.
Report an issue: GitHub.