BigPizzaV3/CodexPlusPlus · error · anyhow::Error
Responses 请求体不是 UTF-8:{error}
Error message
Responses 请求体不是 UTF-8:{error} What it means
After decoding (identity or zstd), decode_protocol_proxy_request_body validates UTF-8 with String::from_utf8 and maps any error to this message (crates/codex-plus-core/src/launcher.rs:1306-1307). The Responses pipeline treats request bodies as JSON text, so a body containing invalid UTF-8 sequences — binary data, wrong-charset text, or a body corrupted/truncated mid-multibyte-character — is rejected before JSON parsing.
Source
Thrown at crates/codex-plus-core/src/launcher.rs:1307
) -> 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": "图片覆盖层未启用或图片不可用"
}))
.unwrap_or_default(),
"application/json; charset=utf-8".to_string(),
"helper.overlay_image_not_found",
)
};
let settings = SettingsStore::default().load().unwrap_or_default();
if !settings.codex_app_image_overlay_enabled {
return not_found();View on GitHub (pinned to 1f431ae49b)
Solutions
- Verify the Content-Encoding actually matches the body bytes — a mismatched zstd label on plain data decodes to garbage that fails this check
- Send genuine UTF-8 JSON: serialize with serde_json (always UTF-8) instead of hand-building strings in a legacy codepage
- If the body is legitimately binary, it does not belong on the Responses text endpoint — move it to a binary upload path
- Reproduce locally: String::from_utf8(body) in a scratch test to see the exact invalid byte offset reported in the error
Example fix
// before: legacy-codepage bytes
let body = encode_cp1252(text); // not UTF-8
post("/responses", body, None).await?; // bail: 请求体不是 UTF-8
// after: UTF-8 JSON
let body = serde_json::to_vec(&payload)?; // guaranteed UTF-8
post("/responses", body, None).await?; Defensive patterns
Strategy: validation
Validate before calling
// Client side: guarantee UTF-8 before sending
let body_str = String::from_utf8(body.clone()).map_err(|e| anyhow!("body not UTF-8: {e}"))?;
// or simply always serialize with serde_json, which emits UTF-8 Type guard
fn body_is_utf8(bytes: &[u8]) -> bool {
std::str::from_utf8(bytes).is_ok()
} Try / catch
match decode_protocol_proxy_request_body(&body, encoding).await {
Err(e) if e.to_string().contains("不是 UTF-8") => {
respond_400_with_detail("request body must be UTF-8 JSON").await
}
rest => rest,
} Prevention
- Always serialize request bodies with serde_json (guaranteed UTF-8) rather than manual string building
- Double-check Content-Encoding matches the actual body bytes — mismatched zstd labels decode to garbage that fails UTF-8
- Avoid truncating request bodies (timeouts, partial reads) which can split multi-byte characters
When it happens
Trigger: A request to the local proxy Responses endpoint whose (decompressed) bytes are not valid UTF-8: a client sending binary in the body, a mis-declared Content-Encoding that makes zstd 'decode' plain bytes into garbage, or truncated uploads that cut a multi-byte UTF-8 sequence in half.
Common situations: Content-Encoding header lying about the body (labeling plain bytes as zstd or vice versa), producing mojibake that fails UTF-8; clients serializing with a non-UTF-8 legacy charset; network truncation from aggressive timeouts; test fixtures generated from raw byte slices.
Related errors
- 解压后的请求体超过大小限制
- throw new Error({});
- 不支持的 Content-Encoding:{encoding}
- downloaded openai/plugins marketplace is invalid
- downloaded openai/plugins marketplace root mismatch
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/3070e7f91636bc65.
Report an issue: GitHub.