{"record":{"id":"859e2d0f06a627d1","repo":"astrid-runtime/astrid","slug":"mcp-gateway-is-already-running-at","errorCode":null,"errorMessage":"MCP gateway is already running at {}","messagePattern":"MCP gateway is already running at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/lifecycle.rs","lineNumber":384,"sourceCode":"    #[cfg(unix)]\n    {\n        use std::os::unix::fs::PermissionsExt;\n        std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o700))?;\n    }\n    Ok(())\n}\n\n/// Bind-time cleanup and endpoint ownership check for a gateway listener.\npub(crate) async fn prepare_gateway_socket(_lifecycle: &GatewayLifecycleLock) -> Result<PathBuf> {\n    let path = gateway_socket_path()?;\n    let parent = path\n        .parent()\n        .ok_or_else(|| anyhow::anyhow!(\"MCP gateway socket path has no parent\"))?;\n    ensure_private_dir(parent)?;\n\n    if path.exists() {\n        if UnixStream::connect(&path).await.is_ok() {\n            anyhow::bail!(\"MCP gateway is already running at {}\", path.display());\n        }\n        // The lifecycle lock excludes every gateway generation. If the\n        // pathname survived a crash, this holder is now the only process that\n        // may remove and replace it.\n        std::fs::remove_file(&path).with_context(|| {\n            format!(\n                \"failed to remove stale MCP gateway socket {}\",\n                path.display()\n            )\n        })?;\n    }\n    Ok(path)\n}\n\n/// Wait for a ready gateway, starting one child at most once when absent.\npub(crate) async fn wait_for_gateway(principal: &PrincipalId, format: &str) -> Result<ExitCode> {\n    let format = ReadyFormat::parse(format)?;\n    let socket = gateway_socket_path()?;","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/lifecycle.rs#L366-L402","documentation":"Fired by prepare_gateway_socket when the gateway socket path exists and a Unix-stream probe successfully connects to it — meaning another live gateway process already owns the endpoint. Binding a second listener would silently steal or fail against the existing owner.","triggerScenarios":"Thrown at crates/astrid-cli/src/commands/mcp/lifecycle.rs:384 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use the already-running gateway instead of starting a new one (`astrid mcp status`)","Stop the existing gateway before restarting","Remove a stale socket only after confirming no process is listening"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}