{"record":{"id":"efce917abf4d4552","repo":"Pumpkin-MC/Pumpkin","slug":"io-error-0-efce91","errorCode":null,"errorMessage":"IO error: {0}","messagePattern":"IO error: (.+?)","errorType":"error_code","errorClass":"PlayerDataError","httpStatus":null,"severity":"error","filePath":"crates/pumpkin-world/src/data/player_data.rs","lineNumber":21,"sourceCode":"use std::io;\nuse std::path::PathBuf;\nuse tracing::{debug, error};\nuse uuid::Uuid;\n\n/// Manages the storage and retrieval of player data from disk and memory cache.\n///\n/// This struct provides functions to load and save player data to/from NBT files,\n/// with a memory cache to handle player disconnections temporarily.\npub struct PlayerDataStorage {\n    /// Path to the directory where player data is stored\n    data_path: PathBuf,\n    /// Whether player data saving is enabled\n    save_enabled: bool,\n}\n\n#[derive(Debug, thiserror::Error)]\npub enum PlayerDataError {\n    #[error(\"IO error: {0}\")]\n    Io(#[from] io::Error),\n    #[error(\"NBT error: {0}\")]\n    Nbt(String),\n}\n\nimpl PlayerDataStorage {\n    /// Creates a new `PlayerDataStorage` with the specified data path and cache expiration time.\n    pub fn new(data_path: impl Into<PathBuf>, enabled: bool) -> Self {\n        let path = data_path.into();\n        if !path.exists()\n            && let Err(e) = create_dir_all(&path)\n        {\n            error!(\n                \"Failed to create player data directory at {}: {e}\",\n                path.display()\n            );\n        }\n","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-world/src/data/player_data.rs#L3-L39","documentation":"Variant `Io` of `PlayerDataError` in pumpkin-world's player data storage. It is automatically converted (`#[from]`) from `std::io::Error`. The library throws it when file operations for player save data fail — creating directories, reading, or writing the player's NBT data file.","triggerScenarios":"`PlayerDataStorage` read/write of `<world>/playerdata/<uuid>.dat` when the OS returns an error: missing directory, permission denied, disk full.","commonSituations":"Read-only world directory, world folder deleted or moved while server runs, permission problems after copying worlds between users/containers, disk quota exceeded.","solutions":["Check the wrapped io::Error message and fix the underlying filesystem issue (permissions, disk space)","Ensure the playerdata directory exists and is writable by the server process","Verify the world data path configured for `PlayerDataStorage::new` is correct"],"exampleFix":"// before: assuming playerdata dir exists\nlet path = data_path.join(format!(\"{}.dat\", uuid));\n// after: create it before IO\nstd::fs::create_dir_all(&data_path)?;\nlet path = data_path.join(format!(\"{}.dat\", uuid));","handlingStrategy":"validation","validationCode":"let dir = data_path.as_ref();\nif !dir.exists() { std::fs::create_dir_all(dir)?; }\nlet test = dir.join(\".write_test\");\nstd::fs::File::create(&test).and_then(|_| std::fs::remove_file(&test))?;","typeGuard":"fn playerdata_usable(dir: &Path) -> bool { dir.is_dir() && dir.metadata().map(|m| !m.permissions().readonly()).unwrap_or(false) }","tryCatchPattern":"match storage.load_player_data(uuid) {\n    Err(PlayerDataError::Io(e)) => warn!(\"playerdata IO failed for {uuid}: {e}; using defaults\"),\n    other => other?,\n}","preventionTips":["Create the playerdata directory at storage initialization","Verify write permissions after copying worlds between users/containers","Monitor disk space on the volume hosting world data"],"tags":["io","player-data","filesystem"],"backgroundTag":"file-read-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"}