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

  1. Treat as an invariant violation: log the request URI and file an upstream issue rather than changing inputs.
  2. Use try_pre_sign_v2 so any occurrence surfaces with the reason string from Uri::from_parts instead of being swallowed.
  3. 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

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


AI-assisted analysis of rustfs/rustfs@35af688cd9 (2026-08-20). Data as JSON: /api/errors/bf9bc9d6d4500da2. Report an issue: GitHub.