{"record":{"id":"c90c84457a8dead7","repo":"clockworklabs/SpacetimeDB","slug":"cannot-deserialize-refs-without-a-typespace","errorCode":null,"errorMessage":"cannot deserialize refs without a typespace","messagePattern":"cannot deserialize refs without a typespace","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/bindings-typescript/src/lib/algebraic_type.ts","lineNumber":170,"sourceCode":"        return primitiveSerializers[ty.tag];\n    }\n  },\n  /** @deprecated Use `makeSerializer` instead. */\n  serializeValue(\n    writer: BinaryWriter,\n    ty: AlgebraicTypeType,\n    value: any,\n    typespace?: TypespaceType\n  ) {\n    AlgebraicType.makeSerializer(ty, typespace)(writer, value);\n  },\n  makeDeserializer(\n    ty: AlgebraicTypeType,\n    typespace?: TypespaceType\n  ): Deserializer<any> {\n    if (ty.tag === 'Ref') {\n      if (!typespace)\n        throw new Error('cannot deserialize refs without a typespace');\n      while (ty.tag === 'Ref') ty = typespace.types[ty.value];\n    }\n    switch (ty.tag) {\n      case 'Product':\n        return ProductType.makeDeserializer(ty.value, typespace);\n      case 'Sum':\n        return SumType.makeDeserializer(ty.value, typespace);\n      case 'Array':\n        if (ty.value.tag === 'U8') {\n          return deserializeUint8Array;\n        } else {\n          const deserialize = AlgebraicType.makeDeserializer(\n            ty.value,\n            typespace\n          );\n          return reader => {\n            const length = reader.readU32();\n            const result: any[] = Array(length);","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-typescript/src/lib/algebraic_type.ts#L152-L188","documentation":"Raised by the SpacetimeDB test harness when the module's HTTP handler itself fails while processing the request. Unlike the route-not-found error, match_http_route succeeded and module.call_http_handler(handler_id, request, body) was invoked, but the WASM handler errored or trapped (panic, host-call failure, bad handler logic). The underlying cause is chained into {e}.","triggerScenarios":"call_http_route_get(\"/path\") reaches a registered handler that panics (unwrap on None, out-of-bounds), returns an internal Err, or trips a host-side rejection while executing — e.g. code that unwraps request headers or body that the harness's synthetic request does not carry (empty headers, empty body, http://localhost URI).","commonSituations":"Handler unwraps optional request state the minimal harness request omits; reducer-style code reused in an HTTP handler that assumes client context; bugs that only reproduce under the harness's bare GET request.","solutions":["Read the full cause chain ({e:#}) — it names the panic or error inside the handler; fix the module code it points to.","Make the handler total over the harness's minimal request: no unwraps on headers/body, handle empty input explicitly.","For expected domain failures, return an HTTP error Response (e.g. 4xx/5xx) and assert on status/body in the test instead of letting the handler fail.","Unit-test the handler inside the module with the same empty-header/empty-body request shape."],"exampleFix":"// before\n#[spacetimedb::http_handler]\nfn hello(req: Request) -> Response {\n    let token = req.header(\"authorization\").unwrap(); // panics under harness GET\n    ...\n}\n\n// after\n#[spacetimedb::http_handler]\nfn hello(req: Request) -> Response {\n    match req.header(\"authorization\") {\n        Some(token) => Response::ok(...),\n        None => Response::new(401),\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match instance.call_http_route_get(\"/path\").await {\n    Ok(body) => assert_eq!(body, expected),\n    Err(e) if e.to_string().contains(\"HTTP handler error\") => {\n        // inspect {e:#} cause chain; print module logs before failing\n        panic!(\"handler trapped - check module-side logs: {e:#}\")\n    }\n    Err(e) => panic!(\"unexpected: {e:#}\"),\n}","preventionTips":["Write handlers total over the harness's minimal GET: never unwrap on headers, body, or query params.","Return error-status Responses for domain failures instead of panicking or returning Err.","Unit-test handlers inside the module with an empty-headers/empty-body request before wiring the harness test."],"tags":["spacetimedb","testing","http","wasm","handler","panic"],"backgroundTag":"http-handler-exception","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}