{"record":{"id":"d2ff29813b0b5237","repo":"astrid-runtime/astrid","slug":"shutdown-stage-gateway-authentication-live-gatewa","errorCode":null,"errorMessage":"shutdown stage gateway.authentication: live gateway has no readiness authority","messagePattern":"shutdown stage gateway\\.authentication: live gateway has no readiness authority","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/lifecycle.rs","lineNumber":636,"sourceCode":"        anyhow::bail!(\n            \"shutdown stage gateway.startup_reap: starting gateway PID {gateway_pid} is {outcome:?}\"\n        );\n    }\n    Ok(())\n}\n\nasync fn clean_unowned_gateway_startup(lifecycle: &GatewayLifecycleLock) -> Result<()> {\n    let socket = gateway_socket_path()?;\n    match astrid_core::local_transport::connect_outcome(&socket)\n        .await\n        .context(\"shutdown stage gateway.listener_probe\")?\n    {\n        astrid_core::local_transport::ConnectOutcome::Absent => {},\n        astrid_core::local_transport::ConnectOutcome::Stale => {\n            astrid_core::local_transport::remove_stale_endpoint(&socket)\n                .context(\"shutdown stage gateway.stale_listener_cleanup\")?;\n        },\n        astrid_core::local_transport::ConnectOutcome::Connected(_) => anyhow::bail!(\n            \"shutdown stage gateway.authentication: live gateway has no readiness authority\"\n        ),\n    }\n    remove_gateway_startup_lease(None).context(\"shutdown stage gateway.startup_cleanup\")?;\n    let _ = lifecycle.file();\n    Ok(())\n}\n\nasync fn request_gateway_control(\n    stream: UnixStream,\n    record: &GatewayReady,\n    operation: GatewayControlOperation,\n) -> Result<GatewayControlAck> {\n    let request = GatewayControlRequest {\n        version: GATEWAY_CONTROL_VERSION,\n        operation,\n        pid: record.pid,\n        hook_token: record.hook_token.clone(),","sourceCodeStart":618,"sourceCodeEnd":654,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/lifecycle.rs#L618-L654","documentation":"Thrown by clean_unowned_gateway_startup when the gateway socket connects successfully (ConnectOutcome::Connected) during cleanup of an unowned startup. A live gateway means there is no readiness authority for this cleanup to proceed, since the process is not owned by this lease.","triggerScenarios":"wait_for_gateway or stop_gateway calls clean_unowned_gateway_startup while another live gateway is listening on the socket — e.g. a gateway started by a different generation/user is still serving.","commonSituations":"A gateway from another terminal session or IDE instance still running; stale lease cleared while the gateway process survived; two clients sharing one socket path with different lifecycles.","solutions":["Stop the live gateway via the client that owns it (its ready record / PID) before cleanup","Verify the socket path: ensure AST/RID gateway socket env/config points to your instance","If the live gateway is legitimately yours, acquire the proper lifecycle lease instead of the unowned-cleanup path","Kill the orphaned process and remove stale socket/lease files"],"exampleFix":"// before\nclean_unowned_gateway_startup(...).await?;\n// after: check for a live gateway first\nif connect_outcome(&gateway_socket_path()?).await\n    == ConnectOutcome::Connected(_) {\n    // route through normal stop_ready_gateway for the live record\n    stop_ready_gateway(...).await?;\n} else {\n    clean_unowned_gateway_startup(...).await?;\n}","handlingStrategy":"fallback","validationCode":"match astrid_core::local_transport::connect_outcome(&gateway_socket_path()?).await? {\n    ConnectOutcome::Connected(_) => anyhow::bail!(\"live gateway present; use owned stop path\"),\n    _ => {},\n}","typeGuard":"fn gateway_is_live(outcome: &ConnectOutcome) -> bool {\n    matches!(outcome, ConnectOutcome::Connected(_))\n}","tryCatchPattern":"match clean_unowned_gateway_startup(...).await {\n    Err(e) if e.to_string().contains(\"no readiness authority\") => {\n        stop_ready_gateway(/* live record */).await?;\n    },\n    other => other?,\n}","preventionTips":["Ensure only one gateway instance uses a given socket path","Stop gateways via the client that owns them","Check for other sessions/IDE instances before forced cleanup"],"tags":["process-management","socket","lifecycle"],"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-17T15:17:12.973Z"}