openai/codex · error · io::Error

network proxy attribution token is not UTF-8

Error message

network proxy attribution token is not UTF-8

What it means

The declared number of token bytes was read successfully but is not valid UTF-8; the ingress requires the attribution token to be a UTF-8 string and rejects with InvalidData. The shipped writer takes &str, so this only happens with hand-built frames: a binary token (raw hash/UUID bytes) or a length prefix that is off, causing framing bytes to be swallowed into the token field.

Source

Thrown at codex-rs/network-proxy/src/attribution.rs:104

        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(
                io::ErrorKind::InvalidData,
                "invalid network proxy attribution token length",
            ));
        }
        let mut token = vec![0_u8; token_len];
        stream.read_exact(&mut token).await?;
        String::from_utf8(token).map_err(|_| {
            io::Error::new(
                io::ErrorKind::InvalidData,
                "network proxy attribution token is not UTF-8",
            )
        })
    })
    .await
    .map_err(|_| {
        io::Error::new(
            io::ErrorKind::TimedOut,
            "network proxy attribution frame timed out",
        )
    })??;

    Ok(Some(token))
}

/// Writes the trusted bridge preface consumed by the shared proxy ingress.
#[doc(hidden)]

View on GitHub (pinned to 339751715c)

Solutions

  1. Pass a UTF-8 string token -- hex- or base64-encode binary ids first.
  2. Recompute token_len as exactly token.as_bytes().len() with no header bytes included.
  3. Use write_attribution_frame, whose &str parameter rules non-UTF-8 tokens out by construction.

Example fix

// before: raw binary id used as the token
let token: &[u8] = uuid.as_bytes(); // may be non-UTF-8
// after: textual encoding
let token = uuid.to_string(); // ASCII hyphenated form
Defensive patterns

Strategy: validation

Validate before calling

// Reject before writing the frame when building bytes yourself
if std::str::from_utf8(token_bytes).is_err() {
    return Err(io::Error::new(
        io::ErrorKind::InvalidInput,
        "attribution token must be valid UTF-8",
    ));
}

Type guard

fn is_utf8_token(bytes: &[u8]) -> bool {
    std::str::from_utf8(bytes).is_ok()
}

Try / catch

Match io::ErrorKind::InvalidData whose message contains 'not UTF-8': re-encode the token as hex/base64 and recompute token_len; if the token was textual, the length prefix is off -- audit the framing arithmetic.

Prevention

When it happens

Trigger: A custom writer puts raw binary (16-byte UUID, SHA digest) into the token field; token_len is off by the header size so read_exact consumes part of the next field; deliberate fuzz/malformed input after a correct magic.

Common situations: Porting the preface to another language and passing bytes instead of str; length arithmetic that accidentally includes the magic or length fields in token_len.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/d5db8887f1621c79. Report an issue: GitHub.