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

  1. Ensure valid credentials for the requested principal are available before opening the guard uplink.
  2. If anonymous access is intended, pass PrincipalId::anonymous() explicitly instead of a named principal.
  3. Re-run the daemon auth handshake and verify the daemon reports authenticated = true for the uplink.
  4. 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

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

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/d0ba2ba6004d005e. Report an issue: GitHub.