rustfs/rustfs · warning · std::io::Error

invalid X-Amz-Content-Sha256 header value: {err}

Error message

invalid X-Amz-Content-Sha256 header value: {err}

What it means

Before signing a bucket-location request with SigV4, the client parses its own X-Amz-Content-Sha256 constant (the empty-body SHA-256 hex digest, or the literal UNSIGNED-PAYLOAD when secure) into a HeaderValue; this error fires if that constant is not a valid header value. In unmodified builds both constants are well-formed ASCII, so hitting this indicates corrupted constants or a modified fork of rustfs-utils/signer.

Source

Thrown at crates/ecstore/src/client/bucket_cache.rs:188

            signer_type = SignatureType::SignatureAnonymous
        }

        if signer_type == SignatureType::SignatureAnonymous {
            return Ok(req);
        }

        if signer_type == SignatureType::SignatureV2 {
            let req = rustfs_signer::sign_v2(req, 0, &access_key_id, &secret_access_key, is_virtual_style);
            return Ok(req);
        }

        let mut content_sha256 = EMPTY_STRING_SHA256_HASH.to_string();
        if self.secure {
            content_sha256 = UNSIGNED_PAYLOAD.to_string();
        }

        let content_sha256_value = content_sha256.parse().map_err(|err| {
            std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                format!("invalid X-Amz-Content-Sha256 header value: {err}"),
            )
        })?;
        req.headers_mut().insert("X-Amz-Content-Sha256", content_sha256_value);
        let req = rustfs_signer::try_sign_v4(req, 0, &access_key_id, &secret_access_key, &session_token, "us-east-1")
            .map_err(|err| signer_error_to_io_error("failed to sign bucket location request", err))?;
        Ok(req)
    }
}

async fn process_bucket_location_response(
    mut resp: http::Response<Incoming>,
    bucket_name: &str,
    tier_type: &str,
) -> Result<String, std::io::Error> {
    //if resp != nil {
    if resp.status() != StatusCode::OK {

View on GitHub (pinned to 9e6e02ea09)

Solutions

  1. Treat it as a source/build integrity problem: diff your rustfs-utils and rustfs-signer crates against upstream releases.
  2. Restore EMPTY_STRING_SHA256_HASH to the 64-character hex of the empty input and UNSIGNED_PAYLOAD to the literal string UNSIGNED-PAYLOAD.
  3. If it reproduces with pristine dependencies, report it upstream with the constant values observed in your build.
Defensive patterns

Strategy: try-catch

Try / catch

match build_and_sign_location_request(...) {
    Ok(req) => Ok(req),
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => {
        tracing::error!(event = "signing_constant_invalid", "X-Amz-Content-Sha256 constant is not a valid header; treat as build integrity failure");
        Err(e)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Executing the SigV4 bucket-location path while EMPTY_STRING_SHA256_HASH or UNSIGNED_PAYLOAD has been changed to a value containing non-ASCII or illegal bytes - i.e., a patched or corrupted dependency, not any runtime input.

Common situations: Custom forks that patched hash constants; build-environment drift producing a modified vendored rustfs-utils; essentially never observed in stock builds, which is why the error is defensive.

Related errors


AI-assisted analysis of rustfs/rustfs@9e6e02ea09 (2026-08-16). Data as JSON: /api/errors/9ceae0e0832350a1. Report an issue: GitHub.