{"record":{"id":"6048b6197dfb9da3","repo":"astrid-runtime/astrid","slug":"invalid-parent-start-identity","errorCode":null,"errorMessage":"invalid parent start identity","messagePattern":"invalid parent start identity","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-fskit/src/service.rs","lineNumber":410,"sourceCode":"    ))\n}\n\nfn validate_launch_parent(\n    parent: &astrid_core::storage_filesystem::StorageProviderParentLifetimeV1,\n) -> Result<()> {\n    if parent.pid <= 1 || parent.pid == std::process::id() {\n        bail!(\"invalid 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 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 parent start identity\");\n    }\n    #[cfg(any(target_os = \"linux\", target_os = \"macos\"))]\n    if parent.start_identity.is_none() {\n        bail!(\"parent start identity is required on this platform\");\n    }\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[cfg(target_os = \"macos\")]\n    #[test]\n    #[ignore = \"requires an explicit disposable live FSKit lease manifest\"]\n    fn live_managed_callback_lease_is_accepted() {\n        let path = std::env::var(\"ASTRID_FSKIT_TEST_LEASE_MANIFEST\").expect(\"explicit QA manifest\");\n        let bytes = std::fs::read(path).expect(\"read QA manifest\");","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fskit/src/service.rs#L392-L428","documentation":"The optional start_identity field of the parent lifetime record, when present, must be a non-empty string of at most 512 bytes with no control characters. An identity that is empty, too long, or contains control characters is rejected as malformed.","triggerScenarios":"validate_launch_parent sees parent.start_identity = Some(s) where s.is_empty(), s.len() > 512, or s contains control characters — e.g. Some(\"\") used as a placeholder instead of None.","commonSituations":"Code defaulting to Some(String::new()) instead of None; embedding the identity with a trailing newline; very long bundle/exec identifiers pasting in full paths with control bytes.","solutions":["If no start identity applies, pass None instead of Some(empty string)","Trim the identity string and remove control characters before constructing the record","Keep the identity a short, printable identifier (<= 512 bytes)","Validate the identity string at the point of construction"],"exampleFix":"// before\nstart_identity: Some(String::new())\n// after\nstart_identity: (identity.is_empty() { None } else { Some(identity.trim().to_string()) })","handlingStrategy":"validation","validationCode":"fn start_identity_ok(id: &Option<String>) -> bool { id.as_deref().map_or(true, |s| !s.is_empty() && s.len() <= 512 && !s.chars().any(char::is_control)) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use None, not Some(\"\"), when no identity applies","Trim and sanitize identity strings","Keep identities short and printable","Validate at the point of record construction"],"tags":["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"}