{"record":{"id":"17579907b1e05c19","repo":"astrid-runtime/astrid","slug":"mcp-gateway-readiness-path-has-no-parent","errorCode":null,"errorMessage":"MCP gateway readiness path has no parent","messagePattern":"MCP gateway readiness path has no parent","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/lifecycle.rs","lineNumber":325,"sourceCode":"    if record.version != 1\n        || record.pid == 0\n        || record.principal.is_empty()\n        || record.hook_token.is_empty()\n    {\n        anyhow::bail!(\n            \"invalid MCP gateway readiness metadata at {}\",\n            path.display()\n        );\n    }\n    Ok(Some(record))\n}\n\n/// Write readiness metadata without exposing a partial record to attachers.\npub(crate) fn write_gateway_ready(record: &GatewayReady) -> Result<()> {\n    let path = gateway_ready_path()?;\n    let parent = path\n        .parent()\n        .ok_or_else(|| anyhow::anyhow!(\"MCP gateway readiness path has no parent\"))?;\n    ensure_private_dir(parent)?;\n    let temp = path.with_extension(format!(\"ready.tmp.{}\", std::process::id()));\n    let bytes = serde_json::to_vec(record).context(\"failed to encode MCP gateway readiness\")?;\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)\n        .with_context(|| format!(\"failed to publish {}\", path.display()))?;\n    Ok(())\n}\n\n/// Remove this gateway's readiness marker without deleting a successor's.\npub(crate) fn remove_gateway_ready(record: &GatewayReady) -> Result<()> {\n    let path = gateway_ready_path()?;\n    remove_gateway_ready_at(&path, record)","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/lifecycle.rs#L307-L343","documentation":"`write_gateway_ready` publishes readiness metadata atomically (temp file + rename) only after the gateway has authenticated and bound its listener. This error is thrown when the readiness file path has no parent directory — an invariant guard, since the ready path always derives from the runtime home directory in normal operation.","triggerScenarios":"The readiness path (`mcp-gateway.ready`) resolves without a parent directory, i.e. the runtime home/state root is `/` or empty, or the path was misconstructed by the library.","commonSituations":"Misconfigured runtime home pointing at the filesystem root; corrupted path derivation. Effectively unreachable with default configuration.","solutions":["Correct the runtime home / state directory configuration.","Rerun with default settings to bypass any bad override.","File a bug if it occurs with default configuration."],"exampleFix":"// before\nASTRID_RUNTIME_HOME=/ astrid mcp gateway run\n// after\nASTRID_RUNTIME_HOME=$HOME/.local/share/astrid 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_ready(&record) {\n    if e.to_string().contains(\"has no parent\") {\n        eprintln!(\"bad readiness path configuration\");\n    }\n    return Err(e);\n}","preventionTips":["Configure a normal directory as the runtime home","Do not override lifecycle paths to the filesystem root","Validate path configuration at process start","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"}