{"record":{"id":"233b8435fa7540b7","repo":"clockworklabs/SpacetimeDB","slug":"unsupported-type-for-sender-ty","errorCode":null,"errorMessage":"unsupported type for :sender: {ty:?}","messagePattern":"unsupported type for :sender: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/execution/src/lib.rs","lineNumber":47,"sourceCode":"    pub fn from_sender(sender: Identity) -> Self {\n        Self {\n            sender,\n            empty_view_arg_hash: hash_empty_view_args().to_u256(),\n            sender_view_arg_hash: hash_sender_view_args(sender).to_u256(),\n        }\n    }\n\n    pub fn from_auth(auth: &AuthCtx) -> Self {\n        Self::from_sender(auth.caller())\n    }\n}\n\nimpl ParamResolver for ExecutionParams {\n    fn resolve_param(&self, param: ParamSlot, ty: &AlgebraicType) -> AlgebraicValue {\n        match param {\n            PARAM_SENDER if ty.is_identity() => self.sender.into(),\n            PARAM_SENDER if ty.is_bytes() => AlgebraicValue::Bytes(self.sender.to_be_byte_array().into()),\n            PARAM_SENDER => panic!(\"unsupported type for :sender: {ty:?}\"),\n            PARAM_VIEW_ARG_HASH_EMPTY if matches!(ty, AlgebraicType::U256) => {\n                AlgebraicValue::U256(self.empty_view_arg_hash.into())\n            }\n            PARAM_VIEW_ARG_HASH_EMPTY => panic!(\"unsupported type for empty view arg hash: {ty:?}\"),\n            PARAM_VIEW_ARG_HASH_SENDER if matches!(ty, AlgebraicType::U256) => {\n                AlgebraicValue::U256(self.sender_view_arg_hash.into())\n            }\n            PARAM_VIEW_ARG_HASH_SENDER => panic!(\"unsupported type for sender view arg hash: {ty:?}\"),\n            ParamSlot(slot) => panic!(\"unknown physical plan parameter slot: {slot}\"),\n        }\n    }\n}\n\npub trait Datastore {\n    /// Iterator type for table scans\n    type TableIter<'a>: Iterator<Item = RowRef<'a>> + 'a\n    where\n        Self: 'a;","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/execution/src/lib.rs#L29-L65","documentation":"When executing a physical plan, ExecutionParams::resolve_param binds implicit parameter slots: PARAM_SENDER can bind only to parameters declared as Identity or as bytes (sender passed as big-endian bytes); the view-arg-hash slots only to U256; any unknown slot panics too. If the module's declared type for the :sender slot is anything else, resolve_param panics with the offending AlgebraicType. This is a module-ABI constraint: the caller identity can only be supplied to Identity- or bytes-typed parameters.","triggerScenarios":"Executing a plan whose :sender implicit parameter is declared with a non-Identity, non-bytes type — typically a module compiled with an SDK whose caller parameter used a different type (e.g. Address), resolved when the plan binds PARAM_SENDER.","commonSituations":"SDK/server version skew across releases that changed the sender representation; hand-written wasm declaring the sender param as String or a custom type; porting modules between breaking ABI versions.","solutions":["Rebuild and republish the module with an SDK matching the server so the sender parameter is typed Identity.","In module code, use ctx.sender (ReducerContext) or declare the parameter as Identity, not Address/String/custom types.","If a bytes parameter is acceptable, declare it bytes and convert from the identity's big-endian byte array in module code."],"exampleFix":"// before (older SDK ABI): sender parameter declared as Address\n#[reducer]\nfn tick(ctx: &ReducerContext, sender: Address) { /* ... */ }\n\n// after: read the caller from the context as Identity\n#[reducer]\nfn tick(ctx: &ReducerContext) {\n    let sender: Identity = ctx.sender;\n    /* ... */\n}","handlingStrategy":"type-guard","validationCode":"// before publishing, verify the sender slot's declared type\n// (adapt to however you introspect the module; the host allows only these two)\nfn sender_type_supported(ty: &AlgebraicType) -> bool {\n    ty.is_identity() || ty.is_bytes()\n}\n// in your build/publish checks: reject modules whose sender param fails this predicate","typeGuard":"fn sender_type_supported(ty: &AlgebraicType) -> bool { ty.is_identity() || ty.is_bytes() }","tryCatchPattern":null,"preventionTips":["Prefer ctx.sender on ReducerContext over a dedicated sender parameter.","Regenerate module bindings whenever the server or SDK version changes.","Pin SDK and server versions together and verify with a staging publish after upgrades."],"tags":["spacetimedb","wasm","sender","type-mismatch","reducer"],"backgroundTag":"wasm-abi-mismatch","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}