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

  1. Match the documented HttpResponse shape exactly: status:number, headers:Record<string,string>, body:{ raw:{ mime:string, data:string|Buffer|ArrayBuffer } }.
  2. Log JSON.stringify(response) before returning to spot the offending field.
  3. 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

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


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/cb3679af3b4553a0. Report an issue: GitHub.