Pumpkin-MC/Pumpkin · error
failed to add world resource
Error message
failed to add world resource
What it means
This `.expect("failed to add world resource")` fires in CreatureSpawnEvent's `to_wasm_event` when `state.add_world(self.world.clone())` fails to register the event's world as a host-side resource for the plugin. `add_world` returning None/Err means the plugin's resource table could not accept the world handle, so the event cannot be exported to WASM and the host panics instead of sending a broken event.
Solutions
- Check whether the plugin is still loaded/active when this event fires; stop dispatching events to plugins mid-teardown
- Inspect add_world in wasm_host to see what causes it to fail and add a graceful skip (drop the event for that plugin) instead of expect
- Recreate the plugin host state on reload so resource tables are consistent
- Update the WASM runtime or raise resource limits if the table is exhausted
Example fix
// before
let target_world = state
.add_world(self.world.clone())
.expect("failed to add world resource");
// after: skip delivery instead of crashing the server
let Some(target_world) = state.add_world(self.world.clone()) else {
return Event::NoOp; // or log and skip this plugin
}; Defensive patterns
Strategy: fallback
Validate before calling
// before conversion, ensure the plugin host state can hold resources
if state.is_torn_down() || state.resource_slots_remaining() == 0 {
return Event::NoOp; // skip this plugin safely
} Type guard
fn can_deliver(state: &PluginHostState, world: &World) -> bool {
!state.is_torn_down() && state.can_add_world(world)
} Try / catch
// replace expect with graceful degradation
let target_world = match state.add_world(self.world.clone()) {
Some(w) => w,
None => { log::warn!("plugin state unavailable; skipping event"); return Event::NoOp; }
}; Prevention
- Stop dispatching events to plugins during teardown/reload
- Recreate PluginHostState when a plugin reloads
- Monitor WASM resource-table usage for exhaustion
- Avoid .expect in event hot paths; prefer skip-and-log
When it happens
Trigger: `PluginHostState.add_world` fails while converting a CreatureSpawnEvent for delivery to a WASM plugin — typically when the plugin instance's resource table is exhausted, already torn down, or the state handle belongs to a different plugin instance than the event pipeline assumes.
Common situations: Plugin being unloaded/disabled while events are still being dispatched to it; resource-table limits in the WASM runtime; host state created fresh per event batch but shared world Arc assumptions broken after a reload.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- failed to add player resource
- failed to add world resource
- Cannot construct CampfireStartEvent from WASM
- Cannot construct CauldronLevelChangeEvent from WASM
- failed to add player resource
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/2dffa86e72b69a05.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/entity.rs:648
fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self {
match event {
Event::EntityTransformEvent(data) => Self {
entity_id: data.entity_id,
new_entity_id: data.new_entity_id,
transform_reason: data.transform_reason,
cancelled: data.cancelled,
},
_ => panic!("unexpected event type"),
}
}
}
impl ToFromWasmEvent for CreatureSpawnEvent {
fn to_wasm_event(&self, state: &mut PluginHostState) -> Event {
let target_world = state
.add_world(self.world.clone())
.expect("failed to add world resource");
Event::CreatureSpawnEvent(CreatureSpawnEventData {
entity_id: self.entity_id,
entity_type: self.entity_type.clone(),
position: to_wasm_position(self.position),
target_world,
spawn_reason: self.spawn_reason.clone(),
cancelled: self.cancelled,
})
}
fn apply_wasm_event(&mut self, event: Event, state: &mut PluginHostState) {
cleanup_event(&event, state);
if let Event::CreatureSpawnEvent(data) = event {
self.cancelled = data.cancelled;
}
}
fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self {View on GitHub (pinned to 8d4639e25a)