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
- Delete the oversized ledger file (it is derivable state) so Codewhale starts with a default LateUsageLedger.
- Truncate/prune the JSON by hand: keep the newest entries under 1 MiB, preserving the ledger's JSON structure.
- Check whether an old Codewhale version or another process keeps appending to the file; stop that writer or upgrade it to the bounded version.
- 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
- Keep exactly one Codewhale process per state directory so no unbounded writer appends to the ledger.
- Upgrade from pre-bound legacy versions and trim/delete their oversized ledger once.
- Point the session/state directory only at Codewhale's own files.
- After restoring backups, check ledger file sizes before starting.
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
- late usage ledger exceeds its size bound
- invalid late usage deletion marker
- <serde_json deserialization error>
- session accounting was deleted
- session was deleted
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)