Hmbown/CodeWhale · warning · io::Error

<workspace size gate message>

Error message

<workspace size gate message>

What it means

open_or_init_with_cap runs `estimate_workspace_size_bounded` before initializing a snapshot repo. If the estimate fails the size gate, the WorkspaceGate::describe message is returned as an InvalidInput io::Error: either "workspace too large for snapshots: over N bytes ..." (TooLarge, liftable via the max_workspace_gb config) or "workspace has too many files for snapshots: over 200000 entries" (TooManyEntries, independent of the byte cap).

Solutions

  1. For the TooLarge gate, raise `[snapshots] max_workspace_gb` (or MAX_SNAPSHOT_SIZE_MB) in config.
  2. Add the heavy directories (datasets, artifacts) to .gitignore / snapshot excludes — the estimator skips gitignored content.
  3. For TooManyEntries, reduce the number of files in the workspace; raising the byte cap does NOT lift the 200k-entry bound.
  4. Move large data out of the workspace into a sibling directory.

Example fix

// config.toml
// before
[snapshots]
max_workspace_gb = 2
// after
[snapshots]
max_workspace_gb = 20
Defensive patterns

Strategy: validation

Validate before calling

fn quick_size_ok(ws: &Path, cap_gb: u64) -> std::io::Result<bool> {
    let out = std::process::Command::new("du")
        .args(["-sb", "--exclude=node_modules", "--exclude=target"])
        .arg(ws).output()?;
    let bytes: u64 = String::from_utf8_lossy(&out.stdout)
        .split('\t').next().unwrap_or("0").parse().unwrap_or(0);
    Ok(bytes <= cap_gb * 1024 * 1024 * 1024)
}

Prevention

When it happens

Trigger: Opening a snapshot repo on a workspace whose snapshot-eligible content exceeds cap_bytes (from MAX_SNAPSHOT_SIZE_MB / max_workspace_gb), or whose entry count exceeds SIZE_WALK_MAX_ENTRIES (200,000).

Common situations: Pointing codewhale at a monorepo, a directory full of datasets/media, or a tree with hundreds of thousands of small files; an exclude list (.gitignore) that does not cover large build/data dirs.

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/5837abe02cc434f3. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/snapshot/repo.rs:348

            ));
        }

        let _ = ensure_snapshot_dir(&work_tree)?;
        let git_dir = snapshot_git_dir(&work_tree);

        let needs_init = !git_dir.exists();
        if needs_init {
            // First-init size guard. Skipping this on subsequent opens
            // is intentional: paying a workspace walk on every snapshot
            // would defeat the purpose of the cap, and a workspace
            // that fit on first init is allowed to grow within the
            // existing repo's `MAX_SNAPSHOT_SIZE_MB` budget. Users on
            // workspaces that grew past the cap mid-session get the
            // existing aggressive-pruning path in `snapshot()`.
            if let Err(gate) =
                estimate_workspace_size_bounded(&work_tree, cap_bytes, SIZE_WALK_MAX_ENTRIES)
            {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    gate.describe(cap_bytes, workspace),
                ));
            }
            let parent = git_dir.parent().ok_or_else(|| {
                io::Error::new(io::ErrorKind::InvalidInput, "snapshot dir has no parent")
            })?;
            std::fs::create_dir_all(parent)?;
            // `git init` here uses the parent directory as the work tree
            // and stores metadata in `.git`. We then continue to use
            // explicit `--git-dir` / `--work-tree` flags for every other
            // command so behaviour is invariant of cwd.
            let init = crate::dependencies::Git::command()
                .ok_or_else(|| io_other("git not found on PATH"))?
                .arg("init")
                .arg("--quiet")
                .arg(parent)
                .output()

View on GitHub (pinned to 73e0f67d83)