{"record":{"id":"9a0b9c19a34eb302","repo":"clockworklabs/SpacetimeDB","slug":"unable-to-encode-view-return-value","errorCode":null,"errorMessage":"unable to encode view return value","messagePattern":"unable to encode view return value","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings/src/rt.rs","lineNumber":98,"sourceCode":"    note = \"where each `Ti` type implements `SpacetimeType`.\",\n    note = \"\"\n)]\npub trait Reducer<'de, A: Args<'de>> {\n    fn invoke(&self, ctx: &ReducerContext, args: A) -> ReducerResult;\n}\n\n/// Invoke a caller-specific view.\n/// Returns a BSATN encoded `Vec` of rows.\npub fn invoke_view<'a, A: Args<'a>, T: ViewReturn>(\n    view: impl View<'a, A, T>,\n    ctx: ViewContext,\n    args: &'a [u8],\n) -> Vec<u8> {\n    // Deserialize the arguments from a bsatn encoding.\n    let SerDeArgs(args) = bsatn::from_slice(args).expect(\"unable to decode args\");\n    let retn = view.invoke(&ctx, args);\n    let mut buf = IterBuf::take();\n    retn.to_writer(&mut buf).expect(\"unable to encode view return value\");\n    std::mem::take(&mut *buf)\n}\n/// A trait for types representing the execution logic of a caller-specific view.\n#[expect(clippy::duplicated_attributes, reason = \"false positive\")]\n#[diagnostic::on_unimplemented(\n    message = \"invalid view signature\",\n    label = \"this view signature is not valid\",\n    note = \"\",\n    note = \"view signatures must match:\",\n    note = \"    `Fn(&ViewContext, [T1, ...]) -> Vec<Tn> | Option<Tn>`\",\n    note = \"where each `Ti` implements `SpacetimeType`.\",\n    note = \"\"\n)]\npub trait View<'de, A: Args<'de>, T: ViewReturn> {\n    fn invoke(&self, ctx: &ViewContext, args: A) -> T;\n}\n\n/// Invoke an anonymous view.","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/eddf9f5014579a50d4b67630e28b6e15cad9c4af/crates/bindings/src/rt.rs#L80-L116","documentation":"After a view executes, invoke_view serializes the return value to BSATN via retn.to_writer(&mut buf) and unwraps with .expect(\"unable to encode view return value\") (crates/bindings/src/rt.rs:98). The sink is an in-memory IterBuf, so I/O failures are essentially impossible; a failure here would mean the VIEW RETURN TYPE cannot be serialized to BSATN at all — a type that declares SpacetimeType but hits an encoding edge (or interior misuse of a non-serializable value). It is a defensive invariant rather than an expected runtime error.","triggerScenarios":"A view returning a type whose BSATN serialization is fallible and actually errors (exotic custom/algebraic types, or values violating invariants the encoder assumes); memory allocation failure mid-encode surfacing as an error. Ordinary Vec<T>/Option<T>/row returns over well-formed SpacetimeTypes never take this path.","commonSituations":"Practically unreachable for standard types; appears only in tests that construct degenerate return types or if a new type integration in the module crate is unsound. Most developers will never see it.","solutions":["Confirm the view's return type is a supported SpacetimeType composition (rows, Vec, Option, primitives, table handle)","Reduce the view to return Vec<RowType> — the canonical supported shape — and re-test","If reproducible, file the minimal type definition upstream: this expect firing on a declared SpacetimeType is a bug in the bindings/encoder contract"],"exampleFix":"// before\nfn custom(ctx: &ViewContext, ()) -> ExoticCustomType { /* panics at encode */ }\n\n// after\nfn custom(ctx: &ViewContext, ()) -> Vec<UserRow> {\n    ctx.db.user().iter().collect() // canonical, always encodable\n}","handlingStrategy":"validation","validationCode":"// Keep view returns in the canonical always-encodable shapes:\n// Vec<RowT>, Option<RowT>, RowT where RowT: SpacetimeType (table row type).\n// There is no cheap runtime pre-check beyond using supported types.","typeGuard":null,"tryCatchPattern":"// Panic-based invariant; no caller-side catch exists inside the module.\n// Host may catch_unwind around invoke_view and report the view name.\nlet res = std::panic::catch_unwind(AssertUnwindSafe(|| invoke_view(...)));\nres.map_err(|_| anyhow::anyhow!(\"view return type failed BSATN encode; unsupported return shape\"))?;","preventionTips":["Restrict view return types to generated row types and standard containers","Avoid bespoke custom SpacetimeType impls on view returns unless well-tested","If you can reproduce this, minimize the type and report it as a bindings bug"],"tags":["bsatn","serialization","rust","panic","spacetimedb","view"],"backgroundTag":"serialization-failed","analyzedSha":"eddf9f5014579a50d4b67630e28b6e15cad9c4af","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}