Hmbown/CodeWhale · error · anyhow::Error

patch on stdin exceeds the 16 MiB limit

Error message

patch on stdin exceeds the 16 MiB limit

What it means

When reading a patch from stdin, the code caps input at 16 MiB (MAX_STDIN_PATCH_BYTES). It reads LIMIT+1 bytes via `take` and bails if the buffer exceeds the limit, preventing unbounded memory use from an oversized piped input.

Solutions

  1. Narrow the diff before piping (exclude vendored/generated paths: `git diff -- . ':!vendor'`)
  2. Split the patch into chunks under 16 MiB and apply sequentially
  3. Apply the oversized patch directly with `git apply p.diff` from a file, bypassing the stdin path

Example fix

// before
git diff HEAD~5 | codewhale apply   # 20 MiB diff
// after
git diff HEAD~5 -- . ':!vendor' | codewhale apply
Defensive patterns

Strategy: validation

Validate before calling

let size = patch_data.len();
if size > 16 * 1024 * 1024 { /* split or narrow the diff before piping */ }

Prevention

When it happens

Trigger: Piping more than 16 MiB of patch data into the apply command's stdin — e.g. a diff containing large generated assets, lockfiles, or binary blobs rendered as text.

Common situations: Diffing vendored dependencies or snapshot fixtures; an accidental `git diff --no-text` on binaries; CI jobs piping whole-branch mega-diffs.

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/120c6640befec542. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lib.rs:9945

    println!("Applied patch successfully.");
    Ok(())
}

/// Maximum bytes read for a patch on stdin. Generous for large diffs;
/// anything larger is not a patch.
const MAX_STDIN_PATCH_BYTES: u64 = 16 * 1024 * 1024;

fn read_patch_from_stdin() -> Result<String> {
    let stdin = io::stdin();
    if stdin.is_terminal() {
        bail!("No patch file provided and stdin is empty.");
    }
    let mut buffer = String::new();
    stdin
        .take(MAX_STDIN_PATCH_BYTES + 1)
        .read_to_string(&mut buffer)?;
    if buffer.len() as u64 > MAX_STDIN_PATCH_BYTES {
        bail!("patch on stdin exceeds the 16 MiB limit");
    }
    Ok(buffer)
}

async fn run_mcp_command(
    config: &Config,
    workspace: &Path,
    command: McpCommand,
    plugins: &crate::plugins::PluginRegistry,
) -> Result<()> {
    let config_path = config.mcp_config_path();
    let network_policy = config.network.clone().map(|network| {
        crate::network_policy::NetworkPolicyDecider::with_default_audit(network.into_runtime())
    });
    match command {
        McpCommand::Init { force } => {
            let status = init_mcp_config(&config_path, force)?;
            match status {

View on GitHub (pinned to 73e0f67d83)