astrid-runtime/astrid · error
guard uplink authenticated as anonymous instead of requested
Error message
guard uplink authenticated as anonymous instead of requested principal '{principal}' What it means
validate_guard_auth rejects a session guard whose uplink ended up authenticated only as anonymous when the caller requested a specific principal. The guard passes only if the uplink is authenticated, or if the requested principal is deliberately anonymous. This guards against silently falling back to anonymous credentials for a named principal.
Source
Thrown at crates/astrid-cli/src/commands/mcp/session_guard.rs:65
validate_guard_auth(principal, c.is_authenticated())?;
debug!(%principal, "MCP session guard: daemon uplink established");
let mut client = c;
loop {
match client.read_raw_frame().await {
Ok(Some(_)) => {},
Ok(None) => anyhow::bail!("daemon closed guard uplink"),
Err(e) => return Err(e).context("guard uplink read failed"),
}
}
}
fn validate_guard_auth(principal: &astrid_core::PrincipalId, authenticated: bool) -> Result<()> {
if authenticated || *principal == astrid_core::PrincipalId::anonymous() {
return Ok(());
}
anyhow::bail!(
"guard uplink authenticated as anonymous instead of requested principal '{principal}'"
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn guard_auth_accepts_authenticated_principal() {
let principal = astrid_core::PrincipalId::new("sibyl-code").unwrap();
assert!(validate_guard_auth(&principal, true).is_ok());
}
#[test]
fn guard_auth_rejects_anonymous_fallback_for_named_principal() {
let principal = astrid_core::PrincipalId::new("sibyl-code").unwrap();
let err = validate_guard_auth(&principal, false)View on GitHub (pinned to affd8760f4)
Solutions
- Ensure valid credentials for the requested principal are available before opening the guard uplink.
- If anonymous access is intended, pass PrincipalId::anonymous() explicitly instead of a named principal.
- Re-run the daemon auth handshake and verify the daemon reports authenticated = true for the uplink.
- Check daemon and CLI version compatibility for the authentication protocol.
Example fix
// before
let principal = context::resolve_agent(Some("agent-7"))?; // creds missing -> anonymous
hold_guard_uplink(client, &principal).await?;
// after
let principal = context::resolve_agent(Some("agent-7"))?;
ensure_agent_credentials(&principal).await?; // fail before connect, not after
hold_guard_uplink(client, &principal).await?; Defensive patterns
Strategy: validation
Validate before calling
// fail before opening the uplink if credentials for the named principal are absent
if *principal != astrid_core::PrincipalId::anonymous() && !has_credentials(principal) {
anyhow::bail!("no credentials for principal '{principal}'; uplink would fall back to anonymous");
} Type guard
fn is_named_principal(p: &astrid_core::PrincipalId) -> bool {
*p != astrid_core::PrincipalId::anonymous()
} Try / catch
match hold_guard_uplink(client, principal).await {
Err(e) if e.to_string().contains("authenticated as anonymous") => {
eprintln!("guard auth failed; re-run login/credential setup for {principal}");
return Err(e);
},
other => other,
} Prevention
- Always complete the daemon auth handshake and check `authenticated` before entering the guard hold loop.
- Pass PrincipalId::anonymous() explicitly when anonymous access is intended.
- Rotate/renew agent credentials before they expire; expired creds silently downgrade to anonymous.
- Add a test like guard_auth_rejects_anonymous_fallback_for_named_principal to CI for any auth flow change.
When it happens
Trigger: hold_guard_uplink (or test guard_auth_rejects_anonymous_fallback_for_named_principal) calls validate_guard_auth with authenticated == false while principal != PrincipalId::anonymous(), i.e. the daemon's auth handshake failed or fell back to anonymous.
Common situations: Missing or expired agent credentials so the daemon authenticates the uplink as anonymous; misconfigured auth for the principal; daemon version that no longer supports the auth handshake; caller actually intended anonymous access but passed a named principal.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- daemon closed guard uplink
- MCP gateway is ready for principal '{}', not '{}'; run `aos
- MCP gateway control authority is incomplete
- MCP attach registration has an empty host_session_id
- MCP attach registration is missing hook_token
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/d0ba2ba6004d005e.
Report an issue: GitHub.