astrid-runtime/astrid · error
invalid FUSE callback token
Error message
invalid FUSE callback token
What it means
The mount lease's `lease_token` doubles as the callback authentication token and must be 16–4096 bytes with no control characters. A token that is absent, too short/long, or contains control characters is rejected before the FUSE service accepts the lease.
Source
Thrown at crates/astrid-storage-provider-fuse/src/service.rs:209
}
if let Some(identity) = parent.start_identity.as_deref()
&& (identity.is_empty() || identity.len() > 512 || identity.chars().any(char::is_control))
{
bail!("invalid FUSE service parent start identity");
}
#[cfg(target_os = "linux")]
if parent.start_identity.is_none() {
bail!("FUSE service parent start identity is required on Linux");
}
Ok(())
}
fn validate_lease(lease: &StorageMountLeaseV1) -> Result<()> {
if lease.lease_token.len() < 16
|| lease.lease_token.len() > 4096
|| lease.lease_token.chars().any(char::is_control)
{
bail!("invalid FUSE callback token");
}
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.context("read system clock")?
.as_secs();
if lease.expires_at_epoch_secs < now {
bail!("FUSE lease is expired");
}
if !lease.resource_path.is_absolute() || !lease.callback_path.is_absolute() {
bail!("FUSE lease paths must be absolute");
}
if lease.callback_path != lease.resource_path.join("control.sock") {
bail!("FUSE callback path is not the kernel lease endpoint");
}
platform_fs::validate_private_directory(&lease.resource_path)
.context("validate private FUSE lease resource")?;
platform_fs::verify_no_redirects(&lease.resource_path)
.context("reject redirected FUSE lease resource")?;View on GitHub (pinned to affd8760f4)
Solutions
- Regenerate the lease so `lease_token` is a fresh CSPRNG value of ≥16 bytes.
- Strip control characters (trim whitespace/newlines) when loading the token from storage or env.
- Check the lease broker/issuer version and fix token generation at the source.
- Validate the token length before writing lease.json so bad leases never reach the helper.
Example fix
// before lease_token: short_id(), // e.g. 8 chars // after lease_token: generate_token(32), // 32 random bytes, hex-encoded, trimmed
Defensive patterns
Strategy: validation
Validate before calling
fn valid_lease_token(t: &str) -> bool {
(16..=4096).contains(&t.len()) && !t.chars().any(char::is_control)
} Type guard
fn has_valid_lease_token(lease: &StorageMountLeaseV1) -> bool {
(16..=4096).contains(&lease.lease_token.len()) && !lease.lease_token.chars().any(char::is_control)
} Prevention
- Issue lease tokens of 16+ random bytes
- Trim tokens loaded from files/env
- Validate leases at creation, not only at mount time
When it happens
Trigger: `validate_lease` (called from `validate_launch`) finds `lease.lease_token.len() < 16 || > 4096 || contains control chars`.
Common situations: Lease issued by an older/buggy broker with a short token; token read from a file with trailing newline; truncated token in a serialized lease; hand-crafted lease JSON in tests.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid FUSE service parent token
- invalid parent token
- FUSE service parent start identity is required on Linux
- durable capsule {id} has unsafe WIT metadata path {relative}
- git history path must be a relative in-repository path
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/96e2ba35acaabced.
Report an issue: GitHub.