siyuan-note/siyuan · error

handler did not return an object

Error message

handler did not return an object

What it means

Returned when an HTTP request handler's resolved Promise value cannot be turned into a JS object via ToObject (result is null/undefined/number/string). The kernel requires the handler to return a plain object shaped like { status, headers, body } so it can extract the response.

Source

Thrown at kernel/plugin/plugin.go:928

			err = getHandlerErr
			return
		}

		jsRequest, convertErr := requestGoToJs(p, rt, request)
		if convertErr != nil {
			err = convertErr
			return
		}

		invokeFunction(func(rt *goja.Runtime, result *CallResult) {
			if result.Error != nil {
				done <- &handleResult{Error: result.Error}
				return
			}

			responseObj := result.Value.ToObject(rt)
			if responseObj == nil {
				done <- &handleResult{Error: fmt.Errorf("handler did not return an object")}
				return
			}

			// convert response.body?.raw?.data from (string | Buffer | ArrayBuffer) to []byte
			var raw *[]byte
			if bodyValue := responseObj.Get("body"); isJsValueNotNull(bodyValue) {
				// response.body
				if bodyObj := bodyValue.ToObject(rt); bodyObj != nil {
					if rawValue := bodyObj.Get("raw"); isJsValueNotNull(rawValue) {
						// response.body.raw
						if rawObj := rawValue.ToObject(rt); rawObj != nil {
							if dataValue := rawObj.Get("data"); isJsValueNotNull(dataValue) {
								// response.body.raw.data
								dataBytes, convertErr := jsValueToBytes(rt, dataValue)
								if convertErr == nil {
									raw = &dataBytes
									rawObj.Set("data", goja.Null())
								}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Make the handler always return a response object: return { status: 200, headers: {}, body: { raw: { mime: 'text/plain', data: 'ok' } } }.
  2. Add an explicit default response at the end of the handler so no code path falls through.
  3. Type the handler return in TS as Response so the compiler flags missing returns.

Example fix

// before
server.onRequest('GET', '/x', async (req) => {
  if (req.query.bad) return; // undefined -> error
  return { status: 200, body: { raw: { mime: 'text/plain', data: 'ok' } } };
});

// after
server.onRequest('GET', '/x', async (req) => {
  if (req.query.bad) return { status: 400, body: { raw: { mime: 'text/plain', data: 'bad' } } };
  return { status: 200, body: { raw: { mime: 'text/plain', data: 'ok' } } };
});
Defensive patterns

Strategy: type-guard

Validate before calling

function isResponseObject(v: unknown): v is { status: number; headers?: Record<string,string>; body?: unknown } { return !!v && typeof v === 'object' && typeof (v as any).status === 'number'; }

Type guard

function isResponseObject(v: unknown): v is { status: number; headers?: Record<string,string>; body?: unknown } { return !!v && typeof v === 'object' && typeof (v as any).status === 'number'; }

Prevention

When it happens

Trigger: An onRequest HTTP handler returns undefined, null, a primitive, or forgets to return the response object, so result.Value.ToObject(rt) yields nil.

Common situations: Handler function missing a return statement, returning a fetch Response directly instead of a plain {status, headers, body} object, or an early return path that yields nothing.

Related errors


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