{"record":{"id":"36cb017f1a97372f","repo":"Pumpkin-MC/Pumpkin","slug":"cannot-construct-blockreceivegameevent-from-wasm","errorCode":null,"errorMessage":"Cannot construct BlockReceiveGameEvent from WASM","messagePattern":"Cannot construct BlockReceiveGameEvent from WASM","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/block.rs","lineNumber":976,"sourceCode":"            source_entity_id: self\n                .source_entity\n                .as_ref()\n                .map(|e| e.get_entity().entity_id),\n            cancelled: self.cancelled,\n        })\n    }\n\n    fn apply_wasm_event(&mut self, event: Event, state: &mut PluginHostState) {\n        cleanup_event(&event, state);\n        if let Event::BlockReceiveGameEvent(data) = event {\n            self.cancelled = data.cancelled;\n        }\n    }\n\n    fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self {\n        match event {\n            Event::BlockReceiveGameEvent(_) => {\n                panic!(\"Cannot construct BlockReceiveGameEvent from WASM\")\n            }\n            _ => panic!(\"unexpected event type\"),\n        }\n    }\n}\n\nimpl ToFromWasmEvent for BlockShearEntityEvent {\n    fn to_wasm_event(&self, state: &mut PluginHostState) -> Event {\n        let target_world = state\n            .add_world(self.world.clone())\n            .expect(\"failed to add world resource\");\n        let item = state\n            .add_item_stack(Arc::new(Mutex::new(self.item.clone())))\n            .expect(\"failed to add item stack resource\");\n        Event::BlockShearEntityEvent(BlockShearEntityEventData {\n            block_pos: to_wasm_block_position(self.block_pos),\n            target_world,\n            target_entity_id: self.target.get_entity().entity_id,","sourceCodeStart":958,"sourceCodeEnd":994,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/block.rs#L958-L994","documentation":"A deliberate panic in from_wasm_event for BlockReceiveGameEvent. If the WASM Event variant delivered to the converter is BlockReceiveGameEvent itself, the code panics because this event type cannot be reconstructed from the WASM side — it flows only from host to plugin.","triggerScenarios":"The generated plugin dispatch calls from_wasm_event with an Event::BlockReceiveGameEvent payload, meaning an event that should be one-way host->plugin was routed back through the WASM-to-native conversion.","commonSituations":"A macro-generated handler wrongly re-emits the event; plugin code triggers the same event recursively; refactoring swapped to_wasm_event/from_wasm_event usage.","solutions":["Do not forward BlockReceiveGameEvent back into from_wasm_event; cancel/consume it host-side instead.","If recursion is the cause, guard the dispatch so events triggered inside a plugin callback are not re-delivered to the same plugin.","Check the pumpkin-api-macros generated code to ensure the correct conversion direction is used for this event.","Convert the panic into a logged error + event drop for production robustness."],"exampleFix":"// before\nmatch event {\n    Event::BlockReceiveGameEvent(_) => {\n        panic!(\"Cannot construct BlockReceiveGameEvent from WASM\")\n    }\n    _ => panic!(\"unexpected event type\"),\n}\n// after\nmatch event {\n    Event::BlockReceiveGameEvent(_) => {\n        log::warn!(\"BlockReceiveGameEvent cannot be constructed from WASM; dropping\");\n        return Err(ConversionError::UnsupportedDirection);\n    }\n    other => Err(ConversionError::UnexpectedVariant(other.name())),\n}","handlingStrategy":"type-guard","validationCode":"// Only call from_wasm_event for plugin-to-host event types\nassert!(!is_host_to_plugin_only::<BlockReceiveGameEvent>(), \"BlockReceiveGameEvent cannot be constructed from WASM\");","typeGuard":"fn can_construct_from_wasm<E: ToFromWasmEvent>(event: &Event) -> bool {\n    matches!(event, Event::BlockReceiveGameEvent(_)) == false || E::HAS_FROM_WASM\n}","tryCatchPattern":"let result = std::panic::catch_unwind(AssertUnwindSafe(|| convert_from_wasm(event, state)));\nif result.is_err() {\n    log::warn!(\"one-way event cannot be constructed from WASM; ignored\");\n}","preventionTips":["Never re-emit host-to-plugin events from plugin code; use the cancelled flag on the received event instead.","Guard dispatch against recursive delivery of the same event to the originating plugin.","Keep one-way event contracts documented on the trait impl so future events follow the same pattern."],"tags":["wasm","plugin-host","panic","event-conversion"],"backgroundTag":"unsupported-operation","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}