{"record":{"id":"dc0aef97435a80ce","repo":"Pumpkin-MC/Pumpkin","slug":"unable-to-lock","errorCode":null,"errorMessage":"Unable to lock","messagePattern":"Unable to lock","errorType":"error_code","errorClass":"InventoryError","httpStatus":null,"severity":"warning","filePath":"crates/pumpkin-inventory/src/error.rs","lineNumber":10,"sourceCode":"use thiserror::Error;\n\n/// Errors that can occur during inventory operations.\n///\n/// These errors represent various failure conditions when handling inventory\n/// interactions, such as invalid slot indices, permission issues, or protocol errors.\n#[derive(Error, Debug)]\npub enum InventoryError {\n    /// Failed to acquire a lock on an inventory or slot.\n    #[error(\"Unable to lock\")]\n    LockError,\n    /// The specified slot index is invalid or out of bounds.\n    #[error(\"Invalid slot\")]\n    InvalidSlot,\n    /// A player attempted to interact with a container that is closed.\n    ///\n    /// The parameter is the player's entity ID.\n    #[error(\"Player '{0}' tried to interact with a closed container\")]\n    ClosedContainerInteract(i32),\n    /// Multiple players attempted to drag items in the same container simultaneously.\n    #[error(\"Multiple players dragging in a container at once\")]\n    MultiplePlayersDragging,\n    /// Drag operation was performed out of order (e.g., end before start).\n    #[error(\"Out of order dragging\")]\n    OutOfOrderDragging,\n    /// The received inventory packet is malformed or invalid.\n    #[error(\"Invalid inventory packet\")]\n    InvalidPacket,","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-inventory/src/error.rs#L1-L28","documentation":"InventoryError::LockError indicates the library failed to acquire a lock on an inventory or slot while processing an inventory interaction. Pumpkin inventories are shared mutable state guarded by locks (e.g. Mutex/RwLock); this error surfaces when the lock cannot be obtained instead of blocking or panicking.","triggerScenarios":"Concurrent inventory operations on the same container/slot — e.g. two threads (player packet handler and another system like hopper or drag logic) calling into inventory APIs that take the lock simultaneously and the acquisition path reports failure.","commonSituations":"Multiple players manipulating the same chest in the same tick; async tasks contending for a player's inventory during rapid clicks; plugins/systems mutating inventory from outside the main thread.","solutions":["Check whether the lock acquisition uses try_lock; if so, retry on the next tick or queue the operation","Serialize inventory mutations on the main server thread to avoid contention","Log the conflicting actors to identify which systems contend for the same inventory","Avoid holding inventory locks across await points or long operations"],"exampleFix":"// before\nlet mut slot = inventory.try_lock_slot(idx).map_err(|_| InventoryError::LockError)?;\n// after\nlet mut slot = match inventory.try_lock_slot(idx) {\n    Ok(s) => s,\n    Err(_) => return Ok(()), // retry on next interaction; don't error the player\n};","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match inv.try_lock_slot(idx) {\n    Err(InventoryError::LockError) => {\n        // retry next tick or queue the operation instead of failing the player\n    }\n    r => r?,\n}","preventionTips":["Serialize inventory mutations on the main server thread","Never hold inventory locks across await points","Prefer queuing/retrying over try_lock failures rather than surfacing errors to players","Audit external systems (hoppers, plugins) that touch inventories off-thread"],"tags":["inventory","concurrency","locking","rust"],"backgroundTag":"lock-acquisition-failed","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"}