sigoden/dufs · error · anyhow::Error

invalid nonce

Error message

invalid nonce

What it means

HTTP Digest auth nonces must be exactly 34 bytes: 8 hex chars encoding a Unix-seconds timestamp followed by 26 hex chars of digest. `validate_nonce` rejects any nonce with the wrong length as 'invalid nonce' before further parsing.

Solutions

  1. Use the nonce exactly as issued by this server in its WWW-Authenticate challenge.
  2. Check the client's Digest implementation generates/passes the full nonce string.
  3. Inspect the raw Authorization header for truncation or whitespace mangling.
  4. Fall back to Basic auth if the client cannot do Digest correctly.

Example fix

// before
Authorization: Digest username="u", nonce="abc123"  (too short)
// after
Authorization: Digest username="u", nonce="<34-char nonce from server challenge>"
Defensive patterns

Strategy: validation

Validate before calling

fn nonce_wellformed(n: &str) -> bool { n.len() == 34 && n.chars().all(|c| c.is_ascii_hexdigit()) }
if !nonce_wellformed(nonce) { request_new_challenge(); }

Prevention

When it happens

Trigger: A client sends a WWW-Authenticate Digest response whose nonce is not 34 bytes long — e.g. empty, server-generated nonce from a different implementation, or truncated.

Common situations: Custom HTTP clients hand-building Digest headers; replaying nonces from another server; corrupted or cut-off Authorization headers.

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


AI-assisted analysis of sigoden/dufs@fe7fd564f8 (2026-09-09). Data as JSON: /api/errors/f25ec4fc069274d9. Report an issue: GitHub.

Appendix: source

Thrown at src/auth.rs:527

        }
        None
    } else {
        None
    }
}

fn derive_secret_key(user: &str, pass: &str) -> SigningKey {
    let mut hasher = Sha256::new();
    hasher.update(format!("{user}:{pass}").as_bytes());
    let hash = hasher.finalize();
    SigningKey::from_bytes(&hash.into())
}

/// Check if a nonce is still valid.
/// Return an error if it was never valid
fn validate_nonce(nonce: &[u8]) -> Result<bool> {
    if nonce.len() != 34 {
        bail!("invalid nonce");
    }
    //parse hex
    if let Ok(n) = std::str::from_utf8(nonce) {
        //get time
        if let Ok(secs_nonce) = u32::from_str_radix(&n[..8], 16) {
            //check time
            let now = unix_now();
            let secs_now = now.as_secs() as u32;

            if let Some(dur) = secs_now.checked_sub(secs_nonce) {
                //check hash
                let mut h = NONCESTARTHASH.clone();
                h.consume(secs_nonce.to_be_bytes());
                let h = format!("{:x}", h.finalize());
                if h[..26] == n[8..34] {
                    return Ok(dur < DIGEST_AUTH_TIMEOUT);
                }
            }

View on GitHub (pinned to fe7fd564f8)