{"record":{"id":"69798312f82ae475","repo":"astrid-runtime/astrid","slug":"fskit-service-parent-process-is-not-alive","errorCode":null,"errorMessage":"FSKit service parent process is not alive","messagePattern":"FSKit service parent process is not alive","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-fskit/src/service.rs","lineNumber":66,"sourceCode":"///\n/// The caller must be the kernel-created broker. Public provider requests use\n/// the stdio mode and cannot supply this envelope without a live private lease,\n/// callback bearer, and parent lifetime.\npub(crate) async fn run() -> Result<()> {\n    let launch = read_launch()?;\n    validate_launch(&launch)?;\n    let challenge = storage_provider_service_ready_challenge(\n        &launch.parent.token,\n        STORAGE_FILESYSTEM_SERVICE_READY_SCHEMA_V1,\n        crate::PROVIDER_NAME,\n        launch.lease.mount_id.as_uuid(),\n        &launch.control_path,\n        &launch.lease.resource_path,\n        &launch.lease.callback_path,\n    )\n    .map_err(anyhow::Error::msg)?;\n    if !parent_is_alive(&launch.parent) {\n        bail!(\"FSKit service parent process is not alive\");\n    }\n    probe_callback(&launch).await?;\n    let listener = bind_control(&launch.control_path)?;\n    let mut mounted = match crate::native_mount(&launch.lease, &launch.mountpoint).await {\n        Ok(()) => true,\n        Err(error) => {\n            let _ = local_transport::remove_endpoint(&launch.control_path);\n            return Err(error);\n        },\n    };\n    if let Err(error) = crate::validate_mounted_mountpoint(&launch.mountpoint) {\n        let _ = crate::native_unmount(&launch.mountpoint).await;\n        let _ = local_transport::remove_endpoint(&launch.control_path);\n        return Err(error);\n    }\n    let ready = StorageProviderServiceReadyV1 {\n        schema: STORAGE_FILESYSTEM_SERVICE_READY_SCHEMA_V1,\n        provider: crate::PROVIDER_NAME.to_owned(),","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fskit/src/service.rs#L48-L84","documentation":"The FSKit provider service runs as a child launched by a parent (XPC/extension) process; on startup its run loop verifies the parent is still alive via parent_is_alive after deserializing the launch payload. If the parent has already exited (or the recorded pid/ppid is wrong), the service refuses to proceed because it would otherwise serve a control socket nobody legitimately owns.","triggerScenarios":"The parent process crashed or was killed between writing the launch payload and the service's parent_is_alive check; the launch payload's parent identifier is stale or forged; slow startup so the parent times out and exits first.","commonSituations":"Debugger/breakpoints pausing the parent until it times out; kill/restart of the FSKit extension leaving orphaned service invocations; pid reuse or hand-edited launch payloads in tests.","solutions":["Re-trigger the mount from the parent so a fresh service launch happens with a live parent","Check the parent process (ps -p <pid>) referenced in the launch payload to see why it exited; fix its crash/timeout","Avoid long pauses/crashes of the parent during service startup (e.g. remove debugger hold points)","In tests, ensure the simulated parent stays alive until the service completes startup"],"exampleFix":"// before (test)\nlet launch = build_launch(parent_pid_that_exited);\n// after\nlet parent = spawn_parent_and_wait_alive();\nlet launch = build_launch(parent.pid());","handlingStrategy":"try-catch","validationCode":"fn parent_alive(pid: u32) -> bool {\n    std::path::Path::new(&format!(\"/proc/{pid}\")).exists() || {\n        // macOS: probe via kill(pid, 0)\n        unsafe { libc::kill(pid as i32, 0) == 0 }\n    }\n}\n// assert parent_alive(launch.parent) before spawning the service","typeGuard":null,"tryCatchPattern":"if !parent_alive(launch.parent) {\n    // parent died before service startup: relaunch via the parent flow\n    eprintln!(\"FSKit service parent not alive; re-launching mount from parent\");\n}","preventionTips":["Keep the parent alive until the service finishes startup (no long debugger pauses)","Re-trigger mounts from the parent after crashes instead of reusing stale launches","Validate parent pid in tests and wait for readiness","Monitor parent crashes (crash reports) when services fail to start"],"tags":["process-lifecycle","fskit","ipc","macos"],"backgroundTag":"invalid-state-transition","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}