openai/codex · warning · io::Error
empty proxy connection
Error message
empty proxy connection
What it means
A TCP peer connected to the proxy ingress and closed without sending a single byte: the one-byte peek in read_attribution_token returned 0 (EOF). The ingress needs at least one byte to decide whether a connection is an attributed bridge connection (first byte of the magic) or plain passthrough, so an entirely empty connection is rejected with io::ErrorKind::UnexpectedEof instead of being forwarded.
Source
Thrown at codex-rs/network-proxy/src/attribution.rs:78
.environment_id()
.is_some_and(|actual| actual != expected_environment_id)
{
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"network proxy attribution environment mismatch",
)
.into());
}
stream.extensions_mut().insert(Arc::new(state));
self.inner.serve(stream).await.map_err(Into::into)
}
}
async fn read_attribution_token(stream: &mut TcpStream) -> Result<Option<String>, BoxError> {
let mut marker = [0_u8; 1];
let read = stream.stream.peek(&mut marker).await?;
if read == 0 {
return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "empty proxy connection").into());
}
if marker[0] != ATTRIBUTION_FRAME_MAGIC[0] {
return Ok(None);
}
let token = tokio::time::timeout(ATTRIBUTION_FRAME_TIMEOUT, async {
let mut magic = [0_u8; ATTRIBUTION_FRAME_MAGIC.len()];
stream.read_exact(&mut magic).await?;
if &magic != ATTRIBUTION_FRAME_MAGIC {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"invalid network proxy attribution frame",
));
}
let token_len = stream.read_u16().await? as usize;
if token_len == 0 || token_len > MAX_ATTRIBUTION_TOKEN_LEN {
return Err(io::Error::new(View on GitHub (pinned to 339751715c)
Solutions
- If it comes from a probe or scanner, expect it -- log at debug level and move on; point real health checks at an actual health endpoint.
- If it comes from your own bridge client, write the attribution frame (or the first payload byte) immediately after connect rather than dropping the socket.
- Do not gate retry or startup logic on this error; it carries no recoverable state.
Example fix
// before: health check connects, reads, closes -> server peeks 0 bytes // after: send at least one byte, or target a real health endpoint let mut s = TcpStream::connect(addr).await?; s.write_all(b"PING\n").await?;
Defensive patterns
Strategy: try-catch
Try / catch
// Peer behavior cannot be validated in advance; classify at accept time
if let Some(e) = err.downcast_ref::<io::Error>() {
if e.kind() == io::ErrorKind::UnexpectedEof
&& e.to_string().contains("empty proxy connection")
{
// probe or scanner: log at debug, do not retry, do not alert
}
} Prevention
- Aim TCP health checks at a real health endpoint, or make them send at least one byte.
- In bridge clients, write the preface immediately after connect -- never connect speculatively.
- Treat this error as expected noise in metrics, not as a proxy failure.
When it happens
Trigger: Anything that opens a socket and immediately closes it: TCP health checks and port probes (nc -z, telnet, load-balancer checks), port scanners, or a bridge client that connects then crashes/exits before writing the preface.
Common situations: Pointing a generic TCP health check at the proxy port; security scanners sweeping the port; a client bug that connects 'early' and drops the socket before it has anything to write.
Related errors
- line_offset exceeds file length
- unknown network proxy attribution token
- network proxy attribution environment mismatch
- invalid network proxy attribution frame
- invalid network proxy attribution token length
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/d4fa5f0bbb23bf7c.
Report an issue: GitHub.