{"record":{"id":"49c836f1d4f9b35f","repo":"astrid-runtime/astrid","slug":"mcp-gateway-is-ready-for-principal-not","errorCode":null,"errorMessage":"MCP gateway is ready for principal '{}', not '{}'; run `aos mcp ready --format hook` for the active principal","messagePattern":"MCP gateway is ready for principal '(.+?)', not '(.+?)'; run `aos mcp ready --format hook` for the active principal","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/attach.rs","lineNumber":36,"sourceCode":"};\n\n/// Attach this process's stdio to the principal's persistent MCP gateway.\n///\n/// `workspace` is host project context, not an Astrid home or daemon root. It\n/// is sent in a small registration preface so the gateway can preserve the\n/// caller's `cwd://` root while sharing one daemon uplink across windows.\npub(crate) async fn run(_principal: Option<&str>, workspace: Option<&Path>) -> Result<ExitCode> {\n    // The process-wide principal was authenticated before dispatch. Never\n    // treat a registration field as the source of authority for this attach.\n    let caller = crate::principal::current();\n    let socket = gateway_socket_path()?;\n    let ready = read_gateway_ready()?.ok_or_else(|| {\n        anyhow::anyhow!(\n            \"MCP gateway is not ready for principal '{caller}'; run `aos mcp ready --format hook`\"\n        )\n    })?;\n    if ready.principal != caller.to_string() {\n        anyhow::bail!(\n            \"MCP gateway is ready for principal '{}', not '{}'; run `aos mcp ready --format hook` for the active principal\",\n            ready.principal,\n            caller\n        );\n    }\n    let stream = UnixStream::connect(&socket).await.with_context(|| {\n        format!(\n            \"failed to connect to MCP gateway at {}; run `aos mcp ready --format hook`\",\n            socket.display()\n        )\n    })?;\n\n    let registration = build_registration(&caller, workspace, &ready)?;\n    let mut stream = stream;\n    let header =\n        serde_json::to_vec(&registration).context(\"failed to encode MCP attach registration\")?;\n    stream\n        .write_all(&header)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/attach.rs#L18-L54","documentation":"The MCP attach command reads the gateway's ready-file and verifies it was written for the caller's principal. If the ready-file names a different principal than the active caller, attach is refused with this error, because the gateway handshake would authenticate the wrong identity.","triggerScenarios":"Running `aos mcp attach` after switching active principals/agents while a ready-file from a previous `aos mcp ready` (for the old principal) still exists.","commonSituations":"Switching between agents on one machine; running attach from a different shell with a different active principal than the one that ran `mcp ready`; stale ready-file after re-login.","solutions":["Re-run `aos mcp ready --format hook` as the currently active principal to refresh the ready-file","Switch back to the principal the gateway is ready for before attaching","Delete the stale ready-file and redo the ready + attach sequence"],"exampleFix":"// before\n$ aos agent use alice && aos mcp attach   # ready-file still for bob\n// after\n$ aos mcp ready --format hook             # as alice\n$ aos mcp attach","handlingStrategy":"validation","validationCode":"let ready = read_gateway_ready()?;\nif ready.as_ref().map(|r| r.principal.clone()).as_deref() != Some(&caller.to_string()) {\n    // re-run `aos mcp ready --format hook` as the active principal first\n}","typeGuard":"fn ready_matches(ready: &GatewayReady, caller: &PrincipalId) -> bool { ready.principal == caller.to_string() }","tryCatchPattern":"match run_attach().await {\n    Err(e) if e.to_string().contains(\"is ready for principal\") => {\n        run_ready(\"--format hook\")?; // refresh, then retry once\n        run_attach().await\n    }\n    other => other,\n}","preventionTips":["Always run `aos mcp ready` after switching active principals","Re-run ready + attach as one scripted pair","Clean up stale ready-files on principal switch"],"tags":["mcp","state-mismatch","principal"],"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"}