Kuberwastaken/claurst · error · anyhow::Error
invalid bearer token header
Error message
invalid bearer token header: {} What it means
bearer_header_value builds an HTTP `Authorization: Bearer <token>` header from a raw token string. HeaderValue::from_str rejects any string containing non-visible-ASCII bytes (control chars, non-ASCII). The library wraps that rejection in this error, meaning the supplied token itself is not a valid HTTP header value.
Solutions
- Trim whitespace and strip newlines from the token before passing it: token.trim()
- Verify the token source (env var, file, config) doesn't embed control or non-ASCII characters
- Ensure the value is a bearer token, not a certificate/multiline secret
- Log the token length and char classes (not the token) to find offending bytes
Example fix
// before let header = bearer_header_value(&token)?; // after let header = bearer_header_value(token.trim())?;
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_header_value(s: &str) -> bool {
s.bytes().all(|b| (32..=126).contains(&b) || b == b'\t')
} Try / catch
match bearer_header_value(token.trim()) {
Ok(h) => /* use h */,
Err(e) => eprintln!("bad token encoding: {e}"),
} Prevention
- Always token.trim() after reading from env/files
- Reject tokens with non-ASCII bytes at config-load time
- Never paste multi-line secrets into a bearer-token field
When it happens
Trigger: Calling bearer_header_value (directly or via MCP connect/auth flows) with a token containing newlines, CR/LF (header injection), NUL bytes, or non-ASCII UTF-8 characters (e.g. a password or pasted string with smart quotes).
Common situations: Token read from a malformed config file or env var with a trailing newline that wasn't trimmed; pasted token containing invisible whitespace; a token that is actually a multi-line PEM/secret rather than a bearer token.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Token refresh failed
- Bridge register: server returned
- Token exchange failed
- No API key found. Options: - Set ANTHROPIC_API_KEY for…
- Login succeeded but could not obtain a usable credential
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/c066963d49a5ddd5.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/mcp/src/lib.rs:402
/// Subscribe to raw JSON notifications from the transport.
/// Returns an async stream of notification messages.
///
/// For transports that natively support push notifications (e.g., WebSocket),
/// this returns a stream that yields messages directly from the transport.
/// For transports without native push support (e.g., stdio), this returns
/// a stream that polls periodically.
fn subscribe_to_notifications(
&self,
) -> BoxStream<'static, anyhow::Result<serde_json::Value>>;
fn protocol_version(&self) -> &'static str {
LEGACY_PROTOCOL_VERSION
}
}
pub(crate) fn bearer_header_value(token: &str) -> anyhow::Result<HeaderValue> {
HeaderValue::from_str(&format!("Bearer {}", token))
.map_err(|e| anyhow::anyhow!("invalid bearer token header: {}", e))
}
pub(crate) fn is_event_stream_response(response: &reqwest::Response) -> bool {
response
.headers()
.get(CONTENT_TYPE)
.and_then(|value| value.to_str().ok())
.map(|value| value.contains("text/event-stream"))
.unwrap_or(false)
}
pub(crate) fn resolve_legacy_endpoint(base_url: &str, endpoint: &str) -> anyhow::Result<String> {
let endpoint = endpoint.trim();
if endpoint.is_empty() {
anyhow::bail!("legacy SSE endpoint event did not include a POST endpoint");
}
if let Ok(url) = url::Url::parse(endpoint) {
return Ok(url.to_string());
View on GitHub (pinned to b0637c97ec)