headroomlabs-ai/headroom · error · SigV4Error::Sign
bedrock_sigv4_failed
bedrock_sigv4_failed
Error message
sigv4 signing failed: {0} What it means
The aws-sigv4 signing crate rejected the Bedrock request during signing — URL parse failure or malformed header are the canonical causes listed on the variant. Signing happens per-request in sigv4.rs before the outbound call, so this aborts the request before it ever reaches Bedrock.
Source
Thrown at crates/headroom-proxy/src/bedrock/sigv4.rs:94
}
/// Headers that the signer will write into the outbound request.
/// The handler must add every entry to the upstream-bound HeaderMap
/// before sending — Bedrock validates each header against the
/// canonical request.
#[derive(Debug, Clone)]
pub struct SignedHeaders {
pub entries: Vec<(String, String)>,
/// Lowercase hex SHA-256 of the body. Surfaced for tests + logs.
pub signature: String,
}
/// Errors surfaced by the signing path.
#[derive(Debug, Error)]
pub enum SigV4Error {
/// `aws-sigv4` rejected the request (URL parse, malformed header,
/// etc).
#[error("sigv4 signing failed: {0}")]
Sign(String),
/// The signing-params builder rejected the inputs (e.g. missing
/// region — should never happen because we validate at startup).
#[error("sigv4 builder error: {0}")]
Builder(String),
}
/// Sign a Bedrock request and return the headers the handler must add
/// to the outbound request.
///
/// # Cache safety
///
/// The body bytes passed in MUST be the bytes the proxy is about to
/// send upstream. If the compressor mutated the body, those mutated
/// bytes are what get signed — Bedrock will accept because the
/// signature covers the wire payload, not the original.
///
/// # ErrorsView on GitHub (pinned to 322425c43b)
Solutions
- Inspect the {0} inner string — it embeds the aws-sigv4 error and names the offending component (URL vs header).
- Validate/normalize the configured Bedrock endpoint URL at startup (scheme + host well-formed) so bad config fails fast, not per-request.
- Sanitize or drop hop-by-hop and malformed client headers before signing rather than passing them through.
- Pin or align the aws-sigv4 version with what this crate was tested against if an upgrade introduced stricter checks.
Defensive patterns
Strategy: validation
Validate before calling
// Validate the endpoint once at startup
fn valid_upstream(url: &str) -> bool {
url::Url::parse(url).map(|u| matches!(u.scheme(), "http" | "https")).unwrap_or(false)
} Try / catch
match sign_request(&req, &creds, region).await {
Err(SigV4Error::Sign(e)) => {
tracing::error!(error = %e, "signing rejected request");
// fail the request — signing failures are not transient
return Err(ProxyError::InvalidHeader(e));
}
r => r,
} Prevention
- Parse and validate the configured Bedrock endpoint URL at startup.
- Sanitize client-supplied headers before they enter the signing set.
- Pin aws-sigv4 to a tested version.
When it happens
Trigger: Sign() invoked with a URL the signer cannot parse (unusual scheme, invalid characters); a request header value containing bytes/characters aws-sigv4 refuses; an HTTP method or signing configuration the crate's HttpSignatureProblem wrapping rejects.
Common situations: A custom --bedrock-base-url / endpoint override with a malformed URL; injected headers (from client passthrough) containing newlines or non-ASCII that poison signing; version bump of aws-sigv4 tightening validation on previously-tolerated input.
Related errors
- bedrock_upstream_exception
- bedrock_eventstream_missing_event_type
- Bedrock with temporary credentials (AWS_SESSION_TOKEN) requi
- upstream request failed: {0}
- invalid upstream URL: {0}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/9c0730683ba55b48.
Report an issue: GitHub.