astrid-runtime/astrid · error
WinFsp daemon lease exceeds limit
Error message
WinFsp daemon lease exceeds limit
What it means
The WinFsp daemon reads its startup lease (JSON with lease, mountpoint, callback_path) from stdin, capped at MAX_LEASE_BYTES via take(MAX_LEASE_BYTES + 1). If the byte count read exceeds the cap, daemon_main bails rather than parsing an unbounded payload. This is a defensive bound against oversized or malformed IPC input from the parent process.
Source
Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:57
const DAEMON_STOP_TIMEOUT: Duration = Duration::from_secs(30);
const MOUNTPOINT_READY_TIMEOUT: Duration = Duration::from_secs(10);
const MAX_LEASE_BYTES: u64 = 64 * 1024;
#[derive(serde::Deserialize, serde::Serialize)]
struct DaemonStart {
lease: StorageMountLeaseV1,
mountpoint: PathBuf,
}
pub(crate) fn daemon_main() -> Result<()> {
let mut bytes = Vec::new();
std::io::stdin()
.lock()
.take(MAX_LEASE_BYTES + 1)
.read_to_end(&mut bytes)
.context("read WinFsp daemon lease")?;
if bytes.len() as u64 > MAX_LEASE_BYTES {
bail!("WinFsp daemon lease exceeds limit");
}
let start: DaemonStart =
serde_json::from_slice(&bytes).context("decode WinFsp daemon lease")?;
let lease = start.lease;
if (!start.mountpoint.is_absolute() && !is_drive_designator(&start.mountpoint))
|| !lease.callback_path.is_absolute()
{
bail!("WinFsp daemon lease contains a relative endpoint");
}
let runtime = Arc::new(
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.context("start WinFsp callback runtime")?,
);
let callback = CallbackFs::new(lease.clone(), Arc::clone(&runtime))
.map_err(|failure| anyhow::anyhow!("build WinFsp callback filesystem: {failure:?}"))?;View on GitHub (pinned to affd8760f4)
Solutions
- Shrink the lease payload the parent writes to stdin (trim large fields, keep only schema-required data)
- Ensure the parent writes exactly one bounded JSON document and closes stdin
- Verify parent and WinFsp crate versions match so lease layout is what daemon_main expects
- If the workload legitimately needs larger leases, raise MAX_LEASE_BYTES in the crate and rebuild both sides together
Example fix
// before (parent) write_all(serde_json::to_vec(&lease_with_huge_token)?) // after lease.parent.token = compact_token(); // trim to the minimum needed write_all(serde_json::to_vec(&lease)?)
Defensive patterns
Strategy: validation
Validate before calling
let bytes = serde_json::to_vec(&lease)?;
if bytes.len() as u64 > MAX_LEASE_BYTES {
return Err(format!("lease payload {} bytes exceeds limit {}", bytes.len(), MAX_LEASE_BYTES));
} Type guard
fn lease_within_limit(lease: &DaemonStart, max: u64) -> bool {
serde_json::to_vec(lease).map(|b| (b.len() as u64) <= max).unwrap_or(false)
} Try / catch
match daemon_err {
Err(e) if e.to_string().contains("lease exceeds limit") => {
eprintln!("shrink lease payload or raise MAX_LEASE_BYTES");
}
other => other?,
} Prevention
- Serialize the lease and size-check it before writing to stdin
- Keep tokens/paths in the lease minimal
- Pin parent and daemon crate versions together
When it happens
Trigger: The parent process (or any writer to the daemon's stdin) writes a lease document larger than MAX_LEASE_BYTES, e.g. a lease containing huge tokens, deeply nested or extraneous fields, or corrupted/non-JSON garbage of excessive length.
Common situations: Embedding very long control paths or auth tokens into the lease; a parent/child version mismatch where the child expects a leaner lease schema; a bug causing stdin to receive data beyond the lease (e.g. logging written to stdin).
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- WinFsp service launch exceeds limit
- WinFsp service parent process is not alive
- WinFsp service parent start identity is invalid
- WinFsp stop timed out
- provider request exceeds limit
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/f9159c5fba7be120.
Report an issue: GitHub.