astrid-runtime/astrid · error
MCP attach registration principal
Error message
MCP attach registration principal '{}' is not the authenticated gateway principal '{}' What it means
authenticate_registration resolves the principal embedded in the attach registration and compares it to the principal the gateway itself was started for. If the client names a different principal than the authenticated gateway uplink, the request is treated as a forged-principal attempt and rejected. This is an authorization check tying attach requests to the gateway's own identity.
Solutions
- Attach to the gateway socket belonging to your own principal (check which gateway process/lease you started)
- Re-resolve the principal the same way the gateway does (super::lifecycle::resolve_principal) and confirm they match
- Restart the gateway for your principal and rebuild the registration from its fresh readiness record
- Remove stale client config/cache referencing an old principal
Example fix
// before principal: some_other_principal, // after principal: resolve_principal(Some(&my_principal_config))?,
Defensive patterns
Strategy: validation
Validate before calling
let principal = resolve_principal(Some(®.principal))?;
if principal != gateway_state.principal { return Err("attach to your own principal's gateway"); } Try / catch
match authenticate_registration(®, &state) {
Ok(p) => proceed(p),
Err(e) if e.to_string().contains("not the authenticated gateway principal") => reconnect_to_own_socket(),
Err(e) => return Err(e),
} Prevention
- Discover the gateway socket from your own startup lease, not global discovery
- Rebuild registrations after gateway restarts (principal may change)
- Keep per-principal runtime dirs separate
When it happens
Trigger: Calling serve_attach with a registration whose principal field resolves to a PrincipalId different from state.principal; attempting to select another user's/principal's gateway uplink.
Common situations: Multiple gateways running for different principals and the client attached to the wrong socket; stale registration payload reused from a previous gateway instance with a different principal; misconfigured client config pointing at another principal's workspace.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- MCP attach registration hook_token is invalid
- could not authenticate as principal
- guard uplink authenticated as anonymous instead of…
- MCP attach registration is missing hook_token
- MCP gateway control authority is incomplete
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/752db7f039339cc5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/mcp/gateway.rs:946
anyhow::bail!("MCP attach registration has an empty host");
}
if registration.host_session_id.trim().is_empty() {
anyhow::bail!("MCP attach registration has an empty host_session_id");
}
if registration.hook_token.trim().is_empty() {
anyhow::bail!("MCP attach registration is missing hook_token");
}
validate_workspace(®istration.workspace_abs)?;
Ok(())
}
fn authenticate_registration(
registration: &AttachRegistration,
state: &GatewayState,
) -> Result<astrid_core::PrincipalId> {
let principal = super::lifecycle::resolve_principal(Some(®istration.principal))?;
if principal != state.principal {
anyhow::bail!(
"MCP attach registration principal '{}' is not the authenticated gateway principal '{}'",
principal,
state.principal
);
}
if registration.hook_token != state.hook_token {
anyhow::bail!("MCP attach registration hook_token is invalid");
}
Ok(principal)
}
fn mint_hook_token() -> String {
format!(
"{}{}",
Uuid::new_v4().as_simple(),
Uuid::new_v4().as_simple()
)
}View on GitHub (pinned to affd8760f4)