rustfs/rustfs · warning · SignV2Error
failed to build uri from parts: {reason}
Error message
failed to build uri from parts: {reason} What it means
SignV2Error::InvalidUriParts is returned by pre_sign_v2_inner at request_signature_v2.rs:142-145 when http::Uri::from_parts rejects the reassembled URI. The parts are cloned from a URI that already parsed successfully (lines 131-132), so scheme and authority are known-valid, and the new PathAndQuery was validated on the immediately preceding line. The variant is therefore defensive and effectively unreachable in this revision.
Source
Thrown at crates/signer/src/request_signature_v2.rs:52
// Phase 3: Default to SHA-256, SHA-1 becomes optional
// See https://github.com/rustfs/backlog/issues/747 for discussion.
const _SIGN_V4_ALGORITHM: &str = "AWS4-HMAC-SHA256";
const SIGN_V2_ALGORITHM: &str = "AWS";
#[derive(Debug, thiserror::Error)]
pub enum SignV2Error {
#[error("invalid UTF-8 header value for `{name}`")]
InvalidHeaderValue { name: String },
#[error("failed to format signing timestamp: {reason}")]
TimeFormat { reason: String },
#[error("failed to build signing timestamp: {reason}")]
TimeComponent { reason: String },
#[error("failed to encode query parameters: {reason}")]
QueryEncode { reason: String },
#[error("failed to parse uri: {reason}")]
InvalidUri { reason: String },
#[error("failed to build uri from parts: {reason}")]
InvalidUriParts { reason: String },
#[error("failed to convert canonical headers to UTF-8: {reason}")]
CanonicalUtf8 { reason: String },
#[error("failed to parse header value for `{name}`: {reason}")]
HeaderValueParse { name: String, reason: String },
#[error("failed to resolve host address: {0}")]
HostAddr(#[from] HostAddrError),
}
#[derive(Debug)]
struct SignV2Failure {
request: request::Request<Body>,
error: SignV2Error,
}
type SignV2Outcome = std::result::Result<request::Request<Body>, Box<SignV2Failure>>;
fn sign_v2_fail(request: request::Request<Body>, error: SignV2Error) -> SignV2Outcome {View on GitHub (pinned to 35af688cd9)
Solutions
- Treat as an invariant violation: log the request URI and file an upstream issue rather than changing inputs.
- Use try_pre_sign_v2 so any occurrence surfaces with the reason string from Uri::from_parts instead of being swallowed.
- Verify the crate version actually built matches this source.
Defensive patterns
Strategy: try-catch
Type guard
fn is_invalid_uri_parts(e: &SignV2Error) -> bool {
matches!(e, SignV2Error::InvalidUriParts { .. })
} Try / catch
Err(e @ SignV2Error::InvalidUriParts { .. }) => {
// defensive variant: from_parts on already-validated parts; report upstream
tracing::error!(error = %e, "signer invariant violated");
return Err(anyhow!("signer invariant violated"));
} Prevention
- Do not hand-assemble URIs via into_parts/from_parts before presigning; use absolute-form URIs.
- Keep the try_ API in calling code so defensive variants are observable.
When it happens
Trigger: No input reaches it in a consistent build: every component handed to Uri::from_parts was already validated. Only memory corruption of the parts struct or a locally modified signer could trigger it.
Common situations: Encountered almost exclusively as an exhaustiveness-match arm, or after someone hand-builds URIs via into_parts/from_parts elsewhere and attributes the failure here. If genuinely observed, capture the original URI and report upstream.
Related errors
- failed to parse uri: {reason}
- failed to resolve host address: {0}
- failed to build uri from parts: {reason}
- failed to build signing timestamp: {reason}
- failed to encode query parameters: {reason}
AI-assisted analysis of rustfs/rustfs@35af688cd9 (2026-08-20).
Data as JSON: /api/errors/bf9bc9d6d4500da2.
Report an issue: GitHub.