{"record":{"id":"17f29dfd36989032","repo":"Pumpkin-MC/Pumpkin","slug":"unexpected-event-17f29d","errorCode":null,"errorMessage":"unexpected event","messagePattern":"unexpected event","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pumpkin-plugin-api/src/events/entity/entity_dye.rs","lineNumber":14,"sourceCode":"use crate::wit::pumpkin::plugin::event::{EntityDyeEventData, Event, EventType};\n\nuse super::super::FromIntoEvent;\n\n/// Event triggered when an entity is dyed.\npub struct EntityDyeEvent;\nimpl FromIntoEvent for EntityDyeEvent {\n    const EVENT_TYPE: EventType = EventType::EntityDyeEvent;\n    type Data = EntityDyeEventData;\n\n    fn data_from_event(event: Event) -> Self::Data {\n        match event {\n            Event::EntityDyeEvent(data) => data,\n            _ => panic!(\"unexpected event\"),\n        }\n    }\n\n    fn data_into_event(data: Self::Data) -> Event {\n        Event::EntityDyeEvent(data)\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":22,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-plugin-api/src/events/entity/entity_dye.rs#L1-L22","documentation":"This panic fires inside `data_from_event` for EntityDyeEvent when the incoming `Event` is not `Event::EntityDyeEvent`. It is the downcast step from the generic `Event` enum to `EntityDyeEventData`; the catch-all arm panics because the dispatcher is supposed to deliver only the matching variant. Reaching it signals an event-routing invariant violation.","triggerScenarios":"Calling `data_from_event` with any `Event` variant other than `Event::EntityDyeEvent` — wrong-variant manual dispatch, a dispatcher mismatch between `EventType::EntityDyeEvent` and the payload, or harness code reusing the wrong trait impl.","commonSituations":"Test fixtures that build `Event` values by copy-paste from sibling event modules; custom event buses that skip the `EventType` check; version drift between plugin-api and the host server.","solutions":["Ensure events are wrapped as `Event::EntityDyeEvent(data)` before dispatch","Validate `event_type() == EventType::EntityDyeEvent` before calling `data_from_event`","Synchronize plugin-api versions between plugin and host","Return a `Result`/log from the catch-all arm rather than panicking if you need resilience"],"exampleFix":"// before\n<EntityDyeEvent as Event>::data_from_event(event); // event is Event::EntityExplodeEvent(..)\n// after\nif matches!(event, Event::EntityDyeEvent(_)) {\n    <EntityDyeEvent as Event>::data_from_event(event);\n}","handlingStrategy":"type-guard","validationCode":"if !matches!(event, Event::EntityDyeEvent(_)) { return; }\n<crate::events::entity::entity_dye::EntityDyeEvent as Event>::data_from_event(event);","typeGuard":"fn as_entity_dye(event: &Event) -> Option<&EntityDyeEventData> {\n    match event { Event::EntityDyeEvent(d) => Some(d), _ => None }\n}","tryCatchPattern":"// guard before unwrapping:\nif let Event::EntityDyeEvent(data) = event {\n    // use data\n} else {\n    log::error!(\"misrouted event: expected EntityDyeEvent\");\n}","preventionTips":["Verify the variant with `matches!` before calling `data_from_event`","Dispatch through the event's own `EVENT_TYPE`, not a neighboring impl","Round-trip test each event impl in CI","Align plugin-api and host versions"],"tags":["rust","panic","event-dispatch","plugin-api"],"backgroundTag":"internal-invariant-violation","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"}