Pumpkin-MC/Pumpkin · error

Cannot construct CauldronLevelChangeEvent from WASM

Error message

Cannot construct CauldronLevelChangeEvent from WASM

What it means

This is an intentional `panic!` in `CauldronLevelChangeEvent::from_wasm_event`. Cauldron level changes originate on the server side only; plugins observe them but cannot construct or send them back. Reaching this arm means something attempted the forbidden reverse conversion, so the host aborts to protect event integrity.

Solutions

  1. Never construct/send `CauldronLevelChangeEvent` from plugin code; only implement its handler
  2. Rebuild the plugin against the matching pumpkin-api/WIT version
  3. Review macro-generated dispatch so host-only events are excluded from send paths
  4. Report a pumpkin-api-macros bug if generated code routes this event backwards

Example fix

// before (plugin code)
host.send_event(Event::CauldronLevelChangeEvent(data)); // panics
// after
impl Plugin for MyPlugin {
    fn on_cauldron_level_change(&self, ev: CauldronLevelChangeEvent) { /* observe only */ }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// plugin side: reject host-only events before any send call
if matches!(event, Event::CauldronLevelChangeEvent(_)) {
    log::error!("CauldronLevelChangeEvent cannot be sent from plugins");
    return;
}

Type guard

fn is_plugin_originated(event: &Event) -> bool {
    !matches!(event, Event::CauldronLevelChangeEvent(_))
}

Try / catch

if matches!(event, Event::CauldronLevelChangeEvent(_)) {
    log::error!("rejected reverse conversion of CauldronLevelChangeEvent");
    return;
}

Prevention

When it happens

Trigger: A WASM plugin or generated bridge tries to return/raise `Event::CauldronLevelChangeEvent` to the host, calling `from_wasm_event`.

Common situations: Plugin misuse of an event-send API with a host-only event; macro dispatch bug reversing direction; API version mismatch where event directionality changed.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09). Data as JSON: /api/errors/44f154fadb3788e3. Report an issue: GitHub.

Appendix: source

Thrown at crates/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/block.rs:1148

            new_level: self.new_level,
            reason: format!("{:?}", self.reason),
            entity_id: self.entity.as_ref().map(|e| e.get_entity().entity_id),
            cancelled: self.cancelled,
        })
    }

    fn apply_wasm_event(&mut self, event: Event, state: &mut PluginHostState) {
        cleanup_event(&event, state);
        if let Event::CauldronLevelChangeEvent(data) = event {
            self.new_level = data.new_level;
            self.cancelled = data.cancelled;
        }
    }

    fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self {
        match event {
            Event::CauldronLevelChangeEvent(_) => {
                panic!("Cannot construct CauldronLevelChangeEvent from WASM")
            }
            _ => panic!("unexpected event type"),
        }
    }
}

impl ToFromWasmEvent for CrafterCraftEvent {
    fn to_wasm_event(&self, state: &mut PluginHostState) -> Event {
        let target_world = state
            .add_world(self.world.clone())
            .expect("failed to add world resource");
        let result = state
            .add_item_stack(Arc::new(Mutex::new(self.result.clone())))
            .expect("failed to add item stack resource");
        Event::CrafterCraftEvent(CrafterCraftEventData {
            block_pos: to_wasm_block_position(self.block_pos),
            target_world,
            result,

View on GitHub (pinned to 8d4639e25a)