{"record":{"id":"82e673a37f8799e4","repo":"astrid-runtime/astrid","slug":"mcp-gateway-startup-lease-path-has-no-parent","errorCode":null,"errorMessage":"MCP gateway startup lease path has no parent","messagePattern":"MCP gateway startup lease path has no parent","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/lifecycle.rs","lineNumber":183,"sourceCode":"                || lease\n                    .gateway_exe\n                    .as_ref()\n                    .is_none_or(|path| path.as_os_str().is_empty())\n            {\n                anyhow::bail!(\"invalid MCP gateway startup lease at {}\", path.display());\n            }\n            Ok(Some(lease))\n        },\n        Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(None),\n        Err(error) => Err(error).with_context(|| format!(\"failed to read {}\", path.display())),\n    }\n}\n\npub(crate) fn write_gateway_startup_lease(lease: &GatewayStartupLease) -> Result<()> {\n    let path = gateway_startup_lease_path()?;\n    let parent = path\n        .parent()\n        .ok_or_else(|| anyhow::anyhow!(\"MCP gateway startup lease path has no parent\"))?;\n    ensure_private_dir(parent)?;\n    let temp = path.with_extension(format!(\"starting.tmp.{}\", std::process::id()));\n    let bytes = serde_json::to_vec(lease).context(\"failed to encode MCP gateway startup lease\")?;\n    std::fs::write(&temp, bytes).with_context(|| format!(\"failed to write {}\", temp.display()))?;\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::PermissionsExt;\n        std::fs::set_permissions(&temp, std::fs::Permissions::from_mode(0o600))?;\n    }\n    std::fs::rename(&temp, &path).with_context(|| format!(\"failed to publish {}\", path.display()))\n}\n\npub(crate) fn remove_gateway_startup_lease(boot_token: Option<&str>) -> Result<()> {\n    let path = gateway_startup_lease_path()?;\n    let lease = read_gateway_startup_lease()?;\n    if let Some(lease) = lease\n        && let Some(expected) = boot_token\n        && lease.boot_token != expected","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/lifecycle.rs#L165-L201","documentation":"`write_gateway_startup_lease` writes the startup lease (identity of a gateway holding the lifecycle lock but not yet ready) atomically via a temp file next to the lease path. Before writing, it requires the lease path to have a parent directory; `Path::parent()` returning `None` triggers this error. Like the other \"has no parent\" errors, it is an invariant guard against a degenerate path.","triggerScenarios":"The startup lease path (`mcp-gateway.starting`) resolves to a path with no directory component, which only happens if the runtime home / state root is misconfigured to `/` or a bare root, or if path construction is broken.","commonSituations":"Runtime home misconfigured to the filesystem root; a library bug in lease-path derivation. Not expected in normal operation.","solutions":["Fix the runtime home / state directory configuration so the lease path has a real parent directory.","Retry with default configuration to rule out an override causing the degenerate path.","Report as a bug if it occurs with stock settings."],"exampleFix":"// before\nASTRID_RUNTIME_HOME=/ astrid mcp gateway run\n// after\nunset ASTRID_RUNTIME_HOME && astrid mcp gateway run","handlingStrategy":"validation","validationCode":"let home = std::env::var(\"ASTRID_RUNTIME_HOME\").unwrap_or_default();\nassert!(home != \"/\" && !home.is_empty(), \"runtime home must be a normal directory\");","typeGuard":"fn has_parent(p: &std::path::Path) -> bool { p.parent().is_some() }","tryCatchPattern":"if let Err(e) = write_gateway_startup_lease(&lease) {\n    if e.to_string().contains(\"has no parent\") {\n        eprintln!(\"bad lease path configuration\");\n    }\n    return Err(e);\n}","preventionTips":["Use a real directory for the runtime home/state root","Avoid root-level path overrides","Validate configured paths before starting the gateway","Report occurrences with default config as bugs"],"tags":["mcp","lifecycle","path","invariant"],"backgroundTag":"internal-invariant-violation","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"}