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

  1. Attach to the gateway socket belonging to your own principal (check which gateway process/lease you started)
  2. Re-resolve the principal the same way the gateway does (super::lifecycle::resolve_principal) and confirm they match
  3. Restart the gateway for your principal and rebuild the registration from its fresh readiness record
  4. 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(&reg.principal))?;
if principal != gateway_state.principal { return Err("attach to your own principal's gateway"); }

Try / catch

match authenticate_registration(&reg, &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

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.

Related errors


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(&registration.workspace_abs)?;
    Ok(())
}

fn authenticate_registration(
    registration: &AttachRegistration,
    state: &GatewayState,
) -> Result<astrid_core::PrincipalId> {
    let principal = super::lifecycle::resolve_principal(Some(&registration.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)