Hmbown/CodeWhale · error · io::Error

late usage ledger exceeds its size bound

Error message

late usage ledger {} exceeds its size bound

What it means

When loading the late-usage ledger, read_late_usage_ledger first checks the file's metadata length against the 1 MiB cap (MAX_LATE_USAGE_LEDGER_BYTES) and rejects an oversized file with this InvalidData io::Error before reading any bytes. The message includes the offending path so the user can locate and fix the file. It is the pre-read guard; the read path has a second equivalent check (see error 2334). Thrown from crates/tui/src/session_manager.rs:1494.

Solutions

  1. Delete the oversized ledger file (it is derivable state) so Codewhale starts with a default LateUsageLedger.
  2. Truncate/prune the JSON by hand: keep the newest entries under 1 MiB, preserving the ledger's JSON structure.
  3. Check whether an old Codewhale version or another process keeps appending to the file; stop that writer or upgrade it to the bounded version.
  4. Verify the configured session/state directory points at Codewhale's own files, not an unrelated large file.

Example fix

// before: ledger grown to 4 MiB by an old build, load refuses
Error: late usage ledger /home/me/.local/state/codewhale/late_usage.json exceeds its size bound
// after
$ rm /home/me/.local/state/codewhale/late_usage.json  # or trim to <1MiB, then restart Codewhale
Defensive patterns

Strategy: validation

Validate before calling

let meta = std::fs::metadata(ledger_path)?;
if meta.len() > 1024 * 1024 {
    // oversized before the library opens it: delete or trim now
    std::fs::remove_file(ledger_path)?;
}

Type guard

fn ledger_file_within_bound(path: &Path) -> bool {
    std::fs::metadata(path).map_or(true, |m| m.len() <= 1024 * 1024)
}

Try / catch

match read_late_usage_ledger(path) {
    Ok(ledger) => use(ledger),
    Err(e) if e.to_string().contains("exceeds its size bound") => {
        let _ = std::fs::remove_file(path); // ledger is re-derivable; start fresh
        use(LateUsageLedger::default());
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Opening the ledger file at a session directory path when fs metadata reports len > 1024*1024 — e.g. the file was written by an older build with no bound, appended to repeatedly, or the path points at the wrong/large file (misconfigured session directory).

Common situations: Upgrading Codewhale from a version that never bounded the ledger; a runaway bug that appended entries on every startup; pointing Codewhale's state directory at another large file; restoring a session directory backup that contains a bloated ledger.

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 Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/9bc42bdcd64276f7. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/session_manager.rs:1494

            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "late usage ledger exceeds its size bound",
            ));
        }
        write_atomic(path, &bytes)
    }

    fn load_late_usage_unlocked(path: &Path) -> io::Result<LateUsageLedger> {
        let file = match open_private_read_file(path) {
            Ok(file) => file,
            Err(error) if error.kind() == io::ErrorKind::NotFound => {
                return Ok(LateUsageLedger::default());
            }
            Err(error) => return Err(error),
        };
        let metadata = file.metadata()?;
        if metadata.len() > MAX_LATE_USAGE_LEDGER_BYTES {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "late usage ledger {} exceeds its size bound",
                    path.display()
                ),
            ));
        }
        use std::io::Read as _;
        let mut raw = Vec::with_capacity(
            usize::try_from(metadata.len().min(MAX_LATE_USAGE_LEDGER_BYTES)).unwrap_or(0),
        );
        file.take(MAX_LATE_USAGE_LEDGER_BYTES.saturating_add(1))
            .read_to_end(&mut raw)?;
        if u64::try_from(raw.len()).unwrap_or(u64::MAX) > MAX_LATE_USAGE_LEDGER_BYTES {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "late usage ledger {} exceeds its size bound",

View on GitHub (pinned to 73e0f67d83)