Pumpkin-MC/Pumpkin · critical · WorldInfoError

Io error

Error message

Io error: {0}

What it means

WorldInfoError::IoError(std::io::ErrorKind) is returned when reading or writing world info (level.dat / level.dat_old) fails at the filesystem level. The io::Error is converted into this variant via From<std::io::Error>, keeping only the ErrorKind. It wraps low-level OS failures such as file-not-found, permission-denied, or interrupted reads.

Solutions

  1. Check that the level folder contains a readable level.dat (and level.dat_old) with correct permissions.
  2. Run the server under a user with read/write access to the world directory and ensure the disk has free space.
  3. Match on the returned ErrorKind (NotFound, PermissionDenied, etc.) to apply the appropriate fix or retry.
  4. Restore level.dat from level.dat_old or a backup if the file is corrupt or zero-length.

Example fix

// before: ignoring the kind and crashing on any io failure
let level = reader.read_world_info(&path)?;
// after: handle known io kinds gracefully
match reader.read_world_info(&path) {
    Err(WorldInfoError::IoError(std::io::ErrorKind::NotFound)) => init_fresh_world(&path),
    other => other?,
}
Defensive patterns

Strategy: try-catch

Validate before calling

fn level_dat_readable(level_folder: &Path) -> std::io::Result<()> {
    let f = std::fs::File::open(level_folder.join("level.dat"))?;
    f.metadata()?.permissions().readonly();
    Ok(())
}

Type guard

fn world_info_present(level_folder: &Path) -> bool {
    level_folder.join("level.dat").is_file()
}

Try / catch

match reader.read_world_info(&path) {
    Err(WorldInfoError::IoError(kind)) => match kind {
        std::io::ErrorKind::NotFound => init_new_world(&path),
        std::io::ErrorKind::PermissionDenied => eprintln!("fix permissions on {}", path.display()),
        _ => eprintln!("io failure reading world info: {kind:?}"),
    },
    other => { other?; }
}

Prevention

When it happens

Trigger: AnvilLevelInfo's WorldInfoReader::read_world_info or WorldInfoWriter::write_world_info opens/reads/writes the level folder's level.dat (or its backup) and the underlying std::io operation fails; the From impl at world_info/mod.rs:381 maps it to IoError.

Common situations: level.dat missing from a partially-copied world folder; read-only server directory or insufficient permissions; disk full during a level.dat save; file locked by another process (e.g. backup tool) on Windows.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at crates/pumpkin-world/src/world_info/mod.rs:363

        seed: Seed,
        generator: &crate::generation::generator::VanillaGenerator,
    ) -> Self {
        let mut data = Self::default(seed);
        let spawn_pos = generator.find_spawn_position();
        data.spawn_x = spawn_pos.0.x;
        data.spawn_z = spawn_pos.0.z;
        data
    }

    pub const fn set_pos(&mut self, x: i32, z: i32) {
        self.spawn_x = x;
        self.spawn_z = z;
    }
}

#[derive(Error, Debug)]
pub enum WorldInfoError {
    #[error("Io error: {0}")]
    IoError(std::io::ErrorKind),
    #[error("Info not found!")]
    InfoNotFound,
    #[error("Deserialization error: {0}")]
    DeserializationError(String),
    #[error(
        "No world seed found: neither level.dat nor data/minecraft/world_gen_settings.dat contains one"
    )]
    MissingWorldSeed,
    #[error("Serialization error: {0}")]
    SerializationError(String),
    #[error("Unsupported world data version: {0}")]
    UnsupportedDataVersion(i32),
    #[error("Unsupported world level version: {0}")]
    UnsupportedLevelVersion(i32),
}

impl From<std::io::Error> for WorldInfoError {

View on GitHub (pinned to 8d4639e25a)