astrid-runtime/astrid · error · io::Error

insufficient free space for layout migration: need {required

Error message

insufficient free space for layout migration: need {required} bytes, have {available} bytes

What it means

ensure_available_migration_capacity (via ensure_migration_capacity) requires the target filesystem to hold at least 2× the legacy source size plus a 64 MiB headroom constant before a layout migration may begin; this guarantees both the copy and the not-yet-retired source fit. When available space is below that requirement it returns io::ErrorKind::StorageFull with the exact needed vs. available byte counts. An overflowing requirement (source_bytes near u64::MAX) is rejected separately as 'capacity requirement overflow'.

Source

Thrown at crates/astrid-core/src/dirs_layout.rs:489

)]
fn reject_automatic_windows_layout_one() -> io::Result<()> {
    Ok(())
}

#[cfg(not(target_family = "wasm"))]
fn ensure_migration_capacity(target: &Path, source_bytes: u64) -> io::Result<()> {
    let available = fs2::available_space(target)?;
    ensure_available_migration_capacity(available, source_bytes)
}

#[cfg(not(target_family = "wasm"))]
fn ensure_available_migration_capacity(available: u64, source_bytes: u64) -> io::Result<()> {
    let required = source_bytes
        .checked_mul(2)
        .and_then(|bytes| bytes.checked_add(LAYOUT_MIGRATION_HEADROOM_BYTES))
        .ok_or_else(|| io::Error::other("layout migration capacity requirement overflow"))?;
    if available < required {
        return Err(io::Error::new(
            io::ErrorKind::StorageFull,
            format!(
                "insufficient free space for layout migration: need {required} bytes, have {available} bytes"
            ),
        ));
    }
    Ok(())
}

#[cfg(target_family = "wasm")]
fn ensure_migration_capacity(_target: &Path, _source_bytes: u64) -> io::Result<()> {
    Err(io::Error::new(
        io::ErrorKind::Unsupported,
        "layout migration capacity probing is unavailable in a WebAssembly guest",
    ))
}

fn atomic_write(path: &Path, bytes: &[u8]) -> io::Result<()> {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Free space on the filesystem hosting the Astrid home (need ≥ 2× source size + 64 MiB — the error message states the exact requirement)
  2. Move the Astrid home to a volume with sufficient free space before migrating
  3. Shrink or prune the legacy source data (old state.db/cow content) if legitimately obsolete, lowering the required amount
  4. Check for and raise disk quotas or container storage limits that artificially cap available space

Example fix

// before: 1 GB free, migration needs 2.1 GB
home.begin_layout_v2_migration(&target)?; // StorageFull: need 2201170432 bytes, have 1073741824
// after: free or provision enough space
// df -h /var/lib/astrid  -> ensure >= 2*source + 64MiB
home.begin_layout_v2_migration(&target)?; // proceeds
Defensive patterns

Strategy: validation

Validate before calling

let available = fs2::available_space(home.var_dir())?;
let required = source_bytes * 2 + 64 * 1024 * 1024; // mirror the library rule
if available < required {
    return Err(anyhow!("need {required} bytes free, have {available}"));
}

Type guard

fn has_headroom(available: u64, source_bytes: u64) -> bool {
    source_bytes.checked_mul(2)
        .and_then(|b| b.checked_add(64 * 1024 * 1024))
        .map(|req| available >= req)
        .unwrap_or(false)
}

Try / catch

match home.begin_layout_v2_migration(&target) {
    Err(e) if e.kind() == std::io::ErrorKind::StorageFull => {
        // free space (message shows exact need/have), then retry once
    },
    r => r?,
}

Prevention

When it happens

Trigger: Calling begin_layout_v2_migration (which calls ensure_migration_capacity on var/) when the filesystem hosting the Astrid home has less than 2×state.db/cow size + 64 MiB free. Also triggered directly by tests feeding crafted available/source values.

Common situations: Running a migration on a small or nearly full disk or volume quota; large legacy state.db on a container with a tight overlay filesystem; shared hosting with aggressive disk quotas.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/8058b4b94b92ac33. Report an issue: GitHub.