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

  1. Inspect the state file size (ls -lh) and delete or archive the oversized state file so a fresh one is written
  2. Find what is bloating the state (large task payloads, accumulated results) and narrow/paginate what gets persisted
  3. Point the sub-agent state root at the correct dedicated directory instead of one containing large files
  4. 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

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


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)