Hmbown/CodeWhale · error · anyhow::Error
sub-agent state file
Error message
sub-agent state file {} exceeds the 16 MiB limit What it means
The sub-agent tool loads its persisted state file from disk and enforces a hard 16 MiB cap (MAX_SUBAGENT_STATE_BYTES) so a corrupted or runaway state file cannot exhaust memory. Before the limit test it reads MAX_SUBAGENT_STATE_BYTES + 1 bytes via file.take(...), so any file larger than the cap is detected. When the byte count exceeds the cap, open fails with this anyhow error instead of returning the content.
Solutions
- Inspect the state file size (ls -lh) and delete or archive the oversized state file so a fresh one is written
- Find what is bloating the state (large task payloads, accumulated results) and narrow/paginate what gets persisted
- Point the sub-agent state root at the correct dedicated directory instead of one containing large files
- Raise MAX_SUBAGENT_STATE_BYTES in crates/tui/src/tools/subagent/mod.rs only if your workload genuinely needs more state
Example fix
// before: blindly loading state
let state = load_subagent_state(&path).await?;
// after: check size first and reset if over limit
if fs::metadata(&path)?.len() > 16 * 1024 * 1024 {
fs::remove_file(&path)?; // start a fresh state file
}
let state = load_subagent_state(&path).await?; Defensive patterns
Strategy: validation
Validate before calling
let max = 16 * 1024 * 1024;
if let Ok(meta) = std::fs::metadata(&state_path) {
if meta.len() > max { std::fs::remove_file(&state_path).ok(); }
} Type guard
fn state_file_within_limit(path: &Path, max: u64) -> bool {
std::fs::metadata(path).map(|m| m.len() <= max).unwrap_or(false)
} Try / catch
match load_subagent_state(&path) {
Ok(raw) => raw,
Err(e) if e.to_string().contains("16 MiB") => {
std::fs::remove_file(&path).ok();
Default::default() // fresh state
}
Err(e) => return Err(e),
} Prevention
- Cap what gets persisted into sub-agent state at write time
- Monitor state file sizes and rotate when approaching 16 MiB
- Keep the state root dedicated to sub-agent state, not shared directories
When it happens
Trigger: Calling the sub-agent state load path (open/read of the state file) when the file on disk is larger than 16 MiB; also occurs when the file is exactly at the boundary because one extra byte is read to detect overflow.
Common situations: Long-lived agents accumulating state across many sessions, a crashed writer leaving a bloated or truncated-corrupted state file, or the state root being pointed at the wrong directory so a huge unrelated file sits at the expected path.
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
- agent action=claim widens an enforced write scope, and the…
- Agent has no continuable checkpoint to resume from…
- Agent not found
- Agent continuation target is no longer retained
- Agent continuation target is outside the active session
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/889a0720e2b22a6d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:8929
fn read_subagent_state_file(state_root: &Path, path: &Path) -> Result<String> {
let state_root = normalize_subagent_workspace(state_root);
reject_root_relative_symlinks(&state_root, path)?;
let metadata = fs::symlink_metadata(path)?;
let file_type = metadata.file_type();
if file_type.is_symlink() || !file_type.is_file() {
return Err(anyhow!(
"sub-agent state path must be a regular file: {}",
path.display()
));
}
let file = open_subagent_state_file(path)?;
let mut raw = String::new();
file.take(MAX_SUBAGENT_STATE_BYTES + 1)
.read_to_string(&mut raw)?;
if raw.len() as u64 > MAX_SUBAGENT_STATE_BYTES {
return Err(anyhow!(
"sub-agent state file {} exceeds the 16 MiB limit",
path.display()
));
}
Ok(raw)
}
#[cfg(unix)]
fn open_subagent_state_file(path: &Path) -> Result<fs::File> {
use std::os::unix::fs::OpenOptionsExt;
fs::OpenOptions::new()
.read(true)
.custom_flags(libc::O_NOFOLLOW)
.open(path)
.map_err(Into::into)
}
View on GitHub (pinned to 73e0f67d83)