{"record":{"id":"7b20cb0fe273296a","repo":"astrid-runtime/astrid","slug":"principal-principal-has-no-admitted-durable-ui","errorCode":null,"errorMessage":"principal '{principal}' has no admitted durable UID","messagePattern":"principal '(.+?)' has no admitted durable UID","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/logs.rs","lineNumber":70,"sourceCode":"        if newest.as_ref().is_none_or(|(t, _)| *t < modified) {\n            newest = Some((modified, path));\n        }\n    }\n    Ok(newest.map(|(_, p)| p))\n}\n\nasync fn resolve_principal_uid(principal: &PrincipalId) -> Result<PrincipalUid> {\n    let mut client = crate::admin_client::connect_as_active_agent().await?;\n    let body = client.request(AdminRequestKind::AgentList).await?;\n    let body = crate::admin_client::into_result(body)?;\n    let AdminResponseBody::AgentList(entries) = body else {\n        anyhow::bail!(\"unexpected response while resolving principal UID: {body:?}\");\n    };\n    entries\n        .into_iter()\n        .find(|entry| entry.principal == *principal)\n        .and_then(|entry| entry.owner_uid)\n        .ok_or_else(|| anyhow::anyhow!(\"principal '{principal}' has no admitted durable UID\"))\n}\n\nasync fn resolve_log_dir(principal: &PrincipalId, capsule: Option<&str>) -> Result<PathBuf> {\n    let home = AstridHome::resolve().context(\"Failed to resolve Astrid home directory\")?;\n    Ok(match capsule {\n        // Capsule runtime logs are operational state, not home content. The\n        // daemon's immutable-UID projection owns the canonical path; resolve\n        // the UID through the authenticated admin roster before reading it.\n        Some(name) => home\n            .log_dir()\n            .join(\"principals\")\n            .join(resolve_principal_uid(principal).await?.to_string())\n            .join(name),\n        None => home.log_dir(),\n    })\n}\n\n/// Print the last `n` lines of `path` to stdout. For non-huge logs we","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/logs.rs#L52-L88","documentation":"resolve_principal_uid looks up the authenticated principal in the daemon's admin AgentList roster and extracts its owner_uid (the durable immutable UID used to build the log directory path). If the principal is not in the roster, or its entry has no owner_uid (not yet admitted), the lookup fails with this error.","triggerScenarios":"`astrid logs` for a capsule calls resolve_log_dir -> resolve_principal_uid when: the principal was never admitted to the daemon, the agent hasn't been registered/admitted yet, or the roster entry lacks an owner_uid assignment.","commonSituations":"Querying logs for a brand-new agent before admission completes; typo'd principal id; daemon restarted and roster not yet reloaded; revoked agent whose UID was cleared.","solutions":["Ensure the agent/principal is registered and admitted (`aos agents list` to confirm it appears with an owner_uid)","Re-admit the agent if it is pending, then retry the logs command","Verify the principal id spelling matches the roster entry exactly"],"exampleFix":"// guard before calling\nlet entries = list_agents().await?;\nanyhow::ensure!(\n    entries.iter().any(|e| e.principal == *principal && e.owner_uid.is_some()),\n    \"principal not admitted yet\"\n);","handlingStrategy":"try-catch","validationCode":"// confirm the principal is admitted with a UID before reading capsule logs\nlet entries = agent_list().await?;\nlet admitted = entries.iter().any(|e| e.principal == *principal && e.owner_uid.is_some());\nif !admitted { eprintln!(\"principal '{principal}' not admitted yet\"); }","typeGuard":"fn admitted_with_uid(e: &AgentEntry) -> Option<PrincipalUid> { e.owner_uid }","tryCatchPattern":"match resolve_principal_uid(principal).await {\n    Ok(uid) => uid,\n    Err(e) if e.to_string().contains(\"has no admitted durable UID\") => {\n        eprintln!(\"Admit the agent first (aos agents list/admit), then retry\");\n        return Err(e);\n    }\n}","preventionTips":["Complete agent admission before querying per-capsule logs","Verify principal ids against the roster instead of typing from memory","Handle daemon restarts where the roster may be briefly empty"],"tags":["daemon","admission","uid"],"backgroundTag":"record-not-found","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}