BigPizzaV3/CodexPlusPlus · error
Audio transcriptions 请求缺少 Content-Type
Error message
Audio transcriptions 请求缺少 Content-Type
What it means
Thrown by open_audio_transcriptions_proxy_request in crates/codex-plus-core/src/protocol_proxy.rs when the incoming audio transcriptions request has an empty Content-Type header (after trimming). The proxy must forward the original multipart boundary to the upstream verbatim — it re-sends the raw body with .header(CONTENT_TYPE, content_type) — so without a Content-Type (normally multipart/form-data; boundary=...) the upstream cannot parse the multipart audio upload.
Source
Thrown at crates/codex-plus-core/src/protocol_proxy.rs:815
status_code,
is_stream: false,
content_type,
wire_api: UpstreamWireApi::Responses,
response: upstream,
})
}
pub async fn open_audio_transcriptions_proxy_request(
body: &[u8],
content_type: &str,
original_user_agent: Option<&str>,
) -> anyhow::Result<UpstreamProxyResponse> {
let settings = SettingsStore::default().load().unwrap_or_default();
let relay = crate::relay_rotation::select_relay_for_probe(&settings)?;
validate_upstream(&relay)?;
let content_type = content_type.trim();
if content_type.is_empty() {
anyhow::bail!("Audio transcriptions 请求缺少 Content-Type");
}
let endpoint = audio_transcriptions_url(&relay.base_url);
let _ = crate::diagnostic_log::append_diagnostic_log(
"protocol_proxy.audio_transcriptions_request",
json!({
"relayId": relay.id,
"relayName": relay.name,
"endpoint": endpoint,
"wireApi": UpstreamWireApi::AudioTranscriptions,
"bodyBytes": body.len()
}),
);
let upstream = send_upstream_request(
crate::http_client::proxied_client(&effective_user_agent(
&relay.user_agent,
original_user_agent,
))?View on GitHub (pinned to 1f431ae49b)
Solutions
- Set Content-Type on the client request to the multipart type including the exact boundary used to encode the body, e.g. multipart/form-data; boundary=X
- Prefer a proper multipart helper (reqwest::blocking::multipart, curl -F) so the boundary in the header matches the body
- Verify no intermediate proxy strips the header before the request reaches this endpoint
Example fix
# before curl -X POST http://127.0.0.1:8137/v1/audio/transcriptions --data-binary @audio.mp3 # after curl -X POST http://127.0.0.1:8137/v1/audio/transcriptions -F file=@audio.mp3 -F model=whisper-1
Defensive patterns
Strategy: validation
Validate before calling
let content_type = request
.headers()
.get(reqwest::header::CONTENT_TYPE)
.and_then(|v| v.to_str().ok())
.unwrap_or("")
.trim()
.to_string();
if content_type.is_empty() {
return bad_request("multipart Content-Type with boundary is required");
} Type guard
fn has_multipart_content_type(ct: &str) -> bool {
ct.starts_with("multipart/form-data") && ct.contains("boundary=")
} Prevention
- Always build audio uploads with a multipart helper so the boundary matches the header
- Never strip Content-Type in fronting proxies for the transcriptions endpoint
- Smoke-test audio proxying once after deploying any middleware in front of the proxy
When it happens
Trigger: Calling the /v1/audio/transcriptions proxy path with a client that omitted the Content-Type header; an HTTP client set to strip headers, or code building the multipart body manually and forgetting to set the header; a proxy/framework in front dropping the header.
Common situations: Custom scripts posting audio without multipart tooling; curl invocations missing -H 'Content-Type: multipart/form-data; boundary=...'; middleware that buffers the body and drops the original Content-Type; testing tools that default to no content type.
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/c15974f970628308.
Report an issue: GitHub.