Anuken/Mindustry · error · IOException

Error writing region "{}".

Error message

Error writing region "{}".

What it means

Thrown by SaveFileReader.writeRegion when any Throwable escapes writeChunk while serializing a named save region. writeRegion wraps the chunk write in try/catch and rethrows an IOException tagged with the region name, chaining the cause. This is the write-side counterpart of the read-region error and indicates serialization or IO failure during saving.

Source

Thrown at core/src/mindustry/io/SaveFileReader.java:105

    public void readRegion(String name, DataInput stream, CounterInputStream counter, IORunner<DataInput> cons) throws IOException{
        counter.resetCount();
        int length;
        try{
            length = readChunk(stream, (chunkStream, len) -> cons.accept(chunkStream));
        }catch(Throwable e){
            throw new IOException("Error reading region \"" + name + "\".", e);
        }

        if(length != counter.count - 4){
            throw new IOException("Error reading region \"" + name + "\": read length mismatch. Expected: " + length + "; Actual: " + (counter.count - 4));
        }
    }

    public void writeRegion(String name, DataOutput stream, IORunner<DataOutput> cons) throws IOException{
        try{
            writeChunk(stream, writes -> cons.accept(writes.output));
        }catch(Throwable e){
            throw new IOException("Error writing region \"" + name + "\".", e);
        }
    }

    /** Write a chunk of input to the stream. An integer of some length is written first, followed by the data. */
    public void writeChunk(DataOutput output, IORunner<Writes> runner) throws IOException{
        boolean wasNested = chunkNested;

        chunkNested = true;

        //regions can be nested once, so use a different output if it's already nested
        ReusableByteOutStream dout = wasNested ? byteOutput2 : byteOutput;

        try{
            //reset output position
            dout.reset();
            //write the needed info
            runner.accept(wasNested ? writes2 : writes1);

View on GitHub (pinned to f695ad7e60)

Solutions

  1. Inspect IOException.getCause() for the underlying failure (disk space, permission, NPE).
  2. Free disk space / fix write permissions on the save directory.
  3. If a serialization bug, ensure all written objects implement the expected write path and never write nulls to primitive outputs.
  4. Catch IOException at the save boundary so a failed save doesn't crash the game; keep the previous save intact (write to temp, then rename).

Example fix

// before
SaveIO.write(file);

// after: write to temp then atomically rename, handle failure
try{
    SaveIO.write(tempFile);
    tempFile.moveTo(file);
}catch(IOException e){
    Log.err("Save failed writing region", e.getCause());
    ui.showErrorMessage("Failed to save.");
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check writable target before serializing
if(!file.parent().exists() && !file.parent().mkdirs()){
    throw new IOException("Cannot create save directory");
}
if(file.parent().freeSpace() < minRequiredBytes){
    throw new IOException("Insufficient disk space for save");
}

Try / catch

try{ SaveIO.write(file); }catch(IOException e){ Log.err("Failed writing region", e.getCause()); ui.showErrorMessage("Save failed"); }

Prevention

When it happens

Trigger: Any exception during serialization of a save region (e.g. an object failing to serialize, an IO error writing to the underlying stream, disk full). Bubbles up wrapped as 'Error writing region "<name>".'.

Common situations: Disk full or permission denied while saving; a serializable object throws during write (e.g. null where a primitive expected); a nested writeChunk fails; network save target drops.

Related errors


AI-assisted analysis of Anuken/Mindustry@f695ad7e60 (2026-08-14). Data as JSON: /api/errors/93eea2167977fd9c. Report an issue: GitHub.