sigoden/dufs · error · anyhow::Error
Invalid token
Error message
Invalid token
What it means
`verify_token` hex-decodes a bearer token and requires at least 72 bytes: a 64-byte signature, 8-byte expiry, and a user name. Shorter tokens cannot possibly contain that layout, so they are rejected immediately with 'Invalid token' before signature verification.
Solutions
- Regenerate the token with `Auth::generate_token(path, user)` and use the full returned string.
- Confirm the token is valid hex and sent intact (no truncation by proxies or copy/paste).
- Ensure the Authorization header uses the token format the server expects.
- If tokens come from an older version, re-login/re-issue since formats may differ.
Example fix
// before
let token = "a1b2c3"; // truncated
// after
let token = auth.generate_token("/files", "alice")?; // full 64+8+user hex Defensive patterns
Strategy: try-catch
Validate before calling
fn token_plausible(t: &str) -> bool { t.len() >= 144 && hex::decode(t).map(|r| r.len() >= 72).unwrap_or(false) } Try / catch
match err.downcast_ref::<String>() { Some(m) if m == "Invalid token" => reissue_token_and_retry(), _ => return_401() } Prevention
- Always transmit the complete token string
- Do not hand-edit or truncate tokens
- Re-issue tokens after server upgrades
- Store tokens in variables, not copy-pasted from logs
When it happens
Trigger: Calling `guard` (via `verify_token`) with a token string that is truncated, not the output of `generate_token`, hex-corrupted, or includes only the signature portion.
Common situations: Manually copying part of a token out of logs/URLs; an intermediary stripping characters; hand-crafting tokens for testing; old tokens from a previous token scheme.
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of sigoden/dufs@fe7fd564f8 (2026-09-09).
Data as JSON: /api/errors/da1fc5b284ae9520.
Report an issue: GitHub.
Appendix: source
Thrown at src/auth.rs:184
.ok_or_else(|| anyhow!("Not found user '{user}'"))?;
let exp = unix_now().as_millis() as u64 + TOKEN_EXPIRATION;
let message = format!("{path}:{exp}");
let mut signing_key = derive_secret_key(user, pass);
let sig = signing_key.sign(message.as_bytes()).to_bytes();
let mut raw = Vec::with_capacity(64 + 8 + user.len());
raw.extend_from_slice(&sig);
raw.extend_from_slice(&exp.to_be_bytes());
raw.extend_from_slice(user.as_bytes());
Ok(hex::encode(raw))
}
fn verify_token<'a>(&'a self, token: &str, path: &str) -> Result<(String, &'a AccessPaths)> {
let raw = hex::decode(token)?;
if raw.len() < 72 {
bail!("Invalid token");
}
let sig_bytes = &raw[..64];
let exp_bytes = &raw[64..72];
let user_bytes = &raw[72..];
let exp = u64::from_be_bytes(exp_bytes.try_into()?);
if unix_now().as_millis() as u64 > exp {
bail!("Token expired");
}
let user = std::str::from_utf8(user_bytes)?;
let (pass, ap) = self
.users
.get(user)
.ok_or_else(|| anyhow!("Not found user '{user}'"))?;
let sig = Signature::from_bytes(&<[u8; 64]>::try_from(sig_bytes)?);View on GitHub (pinned to fe7fd564f8)