astrid-runtime/astrid · error

WinFsp service launch exceeds limit

Error message

WinFsp service launch exceeds limit

What it means

The WinFsp private service reads its launch document (StorageProviderServiceLaunchV1) from stdin capped at SERVICE_MAX_LAUNCH_BYTES via take(SERVICE_MAX_LAUNCH_BYTES + 1). If the byte count exceeds the cap, service_main bails before JSON parsing. It is a bounded-read defense for the privileged service's IPC input.

Source

Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:167

    /// Request was rejected.
    Failure { code: String, message: String },
}

const SERVICE_MAX_LAUNCH_BYTES: u64 = 64 * 1024;
const SERVICE_MAX_CONTROL_BYTES: usize = 64 * 1024;
const SERVICE_MAX_CALLBACK_BYTES: usize = 8 * 1024 * 1024;
const SERVICE_POLL: Duration = Duration::from_secs(1);

/// Run the hidden kernel-created `WinFsp` service mode.
pub(crate) fn service_main() -> Result<()> {
    let mut bytes = Vec::new();
    std::io::stdin()
        .lock()
        .take(SERVICE_MAX_LAUNCH_BYTES + 1)
        .read_to_end(&mut bytes)
        .context("read WinFsp service launch")?;
    if bytes.len() as u64 > SERVICE_MAX_LAUNCH_BYTES {
        bail!("WinFsp service launch exceeds limit");
    }
    let launch: StorageProviderServiceLaunchV1 =
        serde_json::from_slice(&bytes).context("decode WinFsp service launch")?;
    validate_service_launch(&launch)?;
    let challenge = storage_provider_service_ready_challenge(
        &launch.parent.token,
        STORAGE_FILESYSTEM_SERVICE_READY_SCHEMA_V1,
        crate::PROVIDER_NAME,
        launch.lease.mount_id.as_uuid(),
        &launch.control_path,
        &launch.lease.resource_path,
        &launch.lease.callback_path,
    )
    .map_err(anyhow::Error::msg)?;
    let runtime = Arc::new(
        tokio::runtime::Builder::new_multi_thread()
            .enable_all()
            .build()

View on GitHub (pinned to affd8760f4)

Solutions

  1. Trim the launch payload the parent writes (shorten tokens/paths, remove non-schema fields)
  2. Have the parent write exactly one JSON document and close stdin
  3. Align parent and service crate versions so the payload shape matches expectations
  4. Raise SERVICE_MAX_LAUNCH_BYTES in the crate only if genuinely needed, rebuilding both binaries together

Example fix

// before
write_all(serde_json::to_vec(&launch_with_full_audit_log)?)
// after
launch.extra = None; // drop oversized optional fields
write_all(serde_json::to_vec(&launch)?)
Defensive patterns

Strategy: validation

Validate before calling

let bytes = serde_json::to_vec(&launch)?;
if bytes.len() as u64 > SERVICE_MAX_LAUNCH_BYTES {
    return Err(format!("launch payload {} bytes exceeds limit {}", bytes.len(), SERVICE_MAX_LAUNCH_BYTES));
}

Type guard

fn launch_within_limit(launch: &StorageProviderServiceLaunchV1, max: u64) -> bool {
    serde_json::to_vec(launch).map(|b| (b.len() as u64) <= max).unwrap_or(false)
}

Try / catch

match service_err {
    Err(e) if e.to_string().contains("launch exceeds limit") => {
        eprintln!("trim launch payload or raise SERVICE_MAX_LAUNCH_BYTES");
    }
    other => other?,
}

Prevention

When it happens

Trigger: The parent writes a launch document larger than SERVICE_MAX_LAUNCH_BYTES to the service's stdin, e.g. oversized token fields, extra nested data, or garbage bytes beyond the JSON document.

Common situations: Embedding very long tokens or control paths in the launch; a parent/child version mismatch inflating the payload; accidental extra writes to the child's stdin pipe.

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


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/53f617ac09036aa2. Report an issue: GitHub.