BigPizzaV3/CodexPlusPlus · error · anyhow::Error

解压后的请求体超过大小限制

Error message

解压后的请求体超过大小限制

What it means

decode_protocol_proxy_request_body (crates/codex-plus-core/src/launcher.rs:1286) decodes Responses-API request bodies forwarded through the local protocol proxy. For Content-Encoding: zstd it streams through a take(MAX_HTTP_BODY_BYTES + 1) reader and rejects anything whose decompressed length exceeds MAX_HTTP_BODY_BYTES (32 MiB, defined at launcher.rs:1874). This is a decompression-bomb guard: a small compressed body that inflates past 32 MiB is refused before it is ever parsed.

Source

Thrown at crates/codex-plus-core/src/launcher.rs:1299

    }
    stream.shutdown().await?;
    Ok(())
}

fn decode_protocol_proxy_request_body(
    body: &[u8],
    content_encoding: Option<&str>,
) -> anyhow::Result<String> {
    let encoding = content_encoding.unwrap_or_default().trim();
    let decoded = if encoding.is_empty() || encoding.eq_ignore_ascii_case("identity") {
        body.to_vec()
    } else if encoding.eq_ignore_ascii_case("zstd") {
        let decoder = zstd::stream::read::Decoder::new(std::io::Cursor::new(body))?;
        let mut limited = decoder.take((MAX_HTTP_BODY_BYTES + 1) as u64);
        let mut decoded = Vec::new();
        limited.read_to_end(&mut decoded)?;
        if decoded.len() > MAX_HTTP_BODY_BYTES {
            anyhow::bail!("解压后的请求体超过大小限制");
        }
        decoded
    } else {
        anyhow::bail!("不支持的 Content-Encoding:{encoding}");
    };

    String::from_utf8(decoded)
        .map_err(|error| anyhow::anyhow!("Responses 请求体不是 UTF-8:{error}"))
}

fn overlay_image_response() -> (String, Vec<u8>, String, &'static str) {
    let not_found = || {
        (
            "404 Not Found".to_string(),
            serde_json::to_vec(&serde_json::json!({
                "status": "failed",
                "message": "图片覆盖层未启用或图片不可用"
            }))

View on GitHub (pinned to 1f431ae49b)

Solutions

  1. Shrink the request: remove inlined base64/attachment payloads from the Responses body or split the session so the serialized request stays under 32 MiB
  2. If you control both ends and legitimately need larger bodies, raise MAX_HTTP_BODY_BYTES in crates/codex-plus-core/src/launcher.rs:1874 and add/adjust the tests at launcher.rs:3211+ that pin the limit
  3. Send the body uncompressed (drop Content-Encoding: zstd) — the raw path still enforces the 32 MiB ceiling but avoids the decode step misreporting
  4. If unexpected, inspect what is actually inflating: capture the compressed size vs decompressed size to distinguish bloat from an attack

Example fix

// before: client inlines a giant artifact
let body = serde_json::to_vec(&request_with_40mb_base64)?; // inflates past limit
proxy_post("/responses", zstd_compress(body), "zstd").await?; // bails

// after: reference instead of inline
request.artifact_url = upload_artifact(&blob).await?; // small body
let body = serde_json::to_vec(&request)?;
proxy_post("/responses", zstd_compress(body), "zstd").await?;
Defensive patterns

Strategy: validation

Validate before calling

// Client side: check compressed AND estimated decompressed size before sending
let compressed = zstd_compress(&body)?;
if body.len() > 32 * 1024 * 1024 {
    anyhow::bail!("body would exceed proxy limit ({} bytes); trim payload", body.len());
}

Type guard

fn within_proxy_limit(decompressed_len: usize) -> bool {
    decompressed_len <= 32 * 1024 * 1024 // MAX_HTTP_BODY_BYTES
}

Try / catch

match decode_protocol_proxy_request_body(&body, encoding).await {
    Err(e) if e.to_string().contains("解压后的请求体超过大小限制") => {
        respond_413_payload_too_large().await // map to 413 for the caller
    }
    rest => rest,
}

Prevention

When it happens

Trigger: A client sends a request to the local proxy's Responses endpoint with Content-Encoding: zstd where the inflated payload exceeds 32 MiB — e.g. enormous conversation state, huge base64 attachments inlined into the request, or a malicious/buggy upstream sending a zstd bomb.

Common situations: Very long Codex sessions whose serialized Responses payload grows past 32 MiB; clients that inline images/base64 blobs into request bodies; a proxy or middleware re-encoding bodies with zstd at high ratios; adversarial traffic against the loopback listener.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16). Data as JSON: /api/errors/5d2219a9b7bf6a7d. Report an issue: GitHub.