Pumpkin-MC/Pumpkin · error

failed to add player resource

Error message

failed to add player resource

What it means

In `ToFromWasmEvent::to_wasm_event` for `PlayerRecipeBookClickEvent`, `state.add_player(self.player.clone()).expect("failed to add player resource")` panics when the host cannot register the player resource in PluginHostState. add_player returns Option/Result and the expect treats None as unrecoverable: the outgoing WASM event requires a valid player resource handle.

Solutions

  1. Check player existence before building the event and skip/consume the event if the player is gone.
  2. Make add_player failure a logged skip rather than a panic (match on None/Err and drop the event).
  3. Clear queued events for a player during disconnect handling so stale events never convert.
  4. Fix any code path that clears PluginHostState while events referencing players are still pending.

Example fix

// before
let player = state
    .add_player(self.player.clone())
    .expect("failed to add player resource");
// after
let Some(player) = state.add_player(self.player.clone()) else {
    tracing::warn!("skipping PlayerRecipeBookClickEvent: player resource unavailable");
    return Event::NoOp; // or skip emission
};
Defensive patterns

Strategy: validation

Validate before calling

if !state.contains_player(&self.player) {
    tracing::warn!("player gone; skipping recipe-book-click event");
    return;
}

Type guard

fn player_available(state: &PluginHostState, p: &PlayerRef) -> bool { state.contains_player(p) }

Try / catch

match state.add_player(self.player.clone()) {
    Ok(player) => build_event(player),
    Err(e) => tracing::warn!("failed to add player resource: {e:?}"),
}

Prevention

When it happens

Trigger: add_player fails to insert/lookup the player — e.g. the player entity no longer exists in host state (left the server mid-event), the resource table is at capacity, or the player key stored on the Rust-side event is stale.

Common situations: Player disconnects between event capture and WASM conversion; a plugin race where events queue for players removed from PluginHostState; host bugs clearing the resource table before pending events flush.

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


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

Appendix: source

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

    }

    fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self {
        match event {
            Event::PlayerPickupArrowEvent(data) => Self {
                player: consume_player(state, &data.player),
                arrow_id: data.arrow_id,
                cancelled: data.cancelled,
            },
            _ => panic!("unexpected event type"),
        }
    }
}

impl ToFromWasmEvent for PlayerRecipeBookClickEvent {
    fn to_wasm_event(&self, state: &mut PluginHostState) -> Event {
        let player = state
            .add_player(self.player.clone())
            .expect("failed to add player resource");
        Event::PlayerRecipeBookClickEvent(PlayerRecipeBookClickEventData {
            player,
            recipe_id: self.recipe_id.clone(),
            make_all: self.make_all,
            cancelled: self.cancelled,
        })
    }

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

    fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self {

View on GitHub (pinned to 8d4639e25a)