{"record":{"id":"30b16277fd4966c7","repo":"astrid-runtime/astrid","slug":"invalid-fuse-service-parent-start-identity","errorCode":null,"errorMessage":"invalid FUSE service parent start identity","messagePattern":"invalid FUSE service parent start identity","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-fuse/src/service.rs","lineNumber":195,"sourceCode":"    Ok(())\n}\n\nfn validate_parent(\n    parent: &astrid_core::storage_filesystem::StorageProviderParentLifetimeV1,\n) -> Result<()> {\n    if parent.pid <= 1 || parent.pid == std::process::id() {\n        bail!(\"invalid FUSE service parent PID\");\n    }\n    if parent.token.len() < 16\n        || parent.token.len() > 512\n        || parent.token.chars().any(char::is_control)\n    {\n        bail!(\"invalid FUSE service parent token\");\n    }\n    if let Some(identity) = parent.start_identity.as_deref()\n        && (identity.is_empty() || identity.len() > 512 || identity.chars().any(char::is_control))\n    {\n        bail!(\"invalid FUSE service parent start identity\");\n    }\n    #[cfg(target_os = \"linux\")]\n    if parent.start_identity.is_none() {\n        bail!(\"FUSE service parent start identity is required on Linux\");\n    }\n    Ok(())\n}\n\nfn validate_lease(lease: &StorageMountLeaseV1) -> Result<()> {\n    if lease.lease_token.len() < 16\n        || lease.lease_token.len() > 4096\n        || lease.lease_token.chars().any(char::is_control)\n    {\n        bail!(\"invalid FUSE callback token\");\n    }\n    let now = SystemTime::now()\n        .duration_since(UNIX_EPOCH)\n        .context(\"read system clock\")?","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fuse/src/service.rs#L177-L213","documentation":"The optional `start_identity` field, when present, must be a non-empty string of at most 512 bytes with no control characters. It identifies the parent's start context; an empty, oversized, or control-character-laden value is rejected by `validate_parent`.","triggerScenarios":"`validate_parent` sees `parent.start_identity` as Some but with `is_empty() || len > 512 || control chars` during `validate_launch`.","commonSituations":"Caller passed `Some(String::new())` to satisfy a type but had no real identity; identity copied from an env var containing a trailing newline; an oversized session/user identity blob exceeding 512 bytes.","solutions":["Pass `None` instead of an empty string when no start identity applies (except on Linux, where it is required).","Trim and sanitize the identity string before embedding it in the launch descriptor.","Shorten the identity (e.g. hash or UUID) to stay under 512 bytes.","Ensure the identity source (env var, config file) is read without control bytes."],"exampleFix":"// before\nstart_identity: Some(String::new()),\n// after\nstart_identity: None, // or Some(sanitized_identity) on Linux","handlingStrategy":"validation","validationCode":"fn valid_identity(id: &Option<String>) -> bool {\n    match id {\n        None => true,\n        Some(s) => !s.is_empty() && s.len() <= 512 && !s.chars().any(char::is_control),\n    }\n}","typeGuard":"fn has_valid_start_identity(parent: &StorageProviderParentLifetimeV1) -> bool {\n    parent.start_identity.as_deref().map_or(true, |s| !s.is_empty() && s.len() <= 512 && !s.chars().any(char::is_control))\n}","tryCatchPattern":null,"preventionTips":["Use None, not Some(String::new()), when there is no identity","Trim and sanitize identity strings from env/config","Keep identities short (UUID/hash) to stay under 512 bytes"],"tags":["fuse","validation","identity"],"backgroundTag":"invalid-argument-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}