astrid-runtime/astrid · error

anyhow::anyhow!(error)

Error message

anyhow::anyhow!(error)

What it means

In `load_lock_from_daemon`, the daemon responded to a `DistroLockGet` admin request with `AdminResponseBody::Error(error)`; the CLI re-raises that daemon-side error string as an anyhow error. It is a pass-through of a server-side failure fetching the distro lock for the given principal, not a client-side parse or connection issue. Any other unexpected response variant gets a distinct 'unexpected distro lock response' error.

Solutions

  1. Read the re-raised daemon error text for the concrete server-side cause and address it there.
  2. Generate the lock first (`astrid distro lock` / install flow) if it doesn't exist yet, then retry regeneration.
  3. Verify the principal has admin rights for the distro lock operation; re-authenticate or use an admin principal.
  4. Check daemon logs around the DistroLockGet handling for the underlying failure (missing/corrupt lock file).
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: only ask when a lock exists server-side
match client.request(AdminRequestKind::DistroLockGet { principal }).await? {
    AdminResponseBody::DistroLock(_) => Ok(()),
    AdminResponseBody::Error(e) => Err(anyhow!("daemon lock unavailable: {e}")),
    other => Err(anyhow!("unexpected response: {other:?}")),
}

Try / catch

match load_lock_from_daemon(&client, &principal).await {
    Err(e) => {
        eprintln!("daemon refused DistroLockGet: {e}");
        // fall back to regenerating locally if authorized
        regenerate_lock_locally(&principal).await
    }
    ok => ok,
}

Prevention

When it happens

Trigger: Calling `regenerate_distro_lock` -> `load_lock_from_daemon` where the daemon returns DistroLock error for the request: lock file missing/corrupt on the daemon side, principal lacks access to the lock, or the daemon's lock store is unavailable.

Common situations: Distro lock never generated before regeneration; running as a principal that isn't authorized for the distro lock admin operation; daemon's workspace state partially initialized so the lock lookup fails server-side.

Related errors


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

Appendix: source

Thrown at crates/astrid-cli/src/commands/distro/lock.rs:161

/// API. JSON field order is fixed by the typed struct declaration.
pub(crate) fn provenance_digest(provenance: &DistroProvenance) -> anyhow::Result<String> {
    let bytes = serde_json::to_vec(provenance).context("encode distro provenance")?;
    Ok(format!("blake3:{}", blake3::hash(&bytes).to_hex()))
}

/// Read the target principal's durable distro record through the daemon.
pub(crate) async fn load_lock_from_daemon(
    principal: &PrincipalId,
) -> anyhow::Result<Option<DistroLock>> {
    let mut client = crate::admin_client::connect_as_active_agent().await?;
    let response = client
        .request(AdminRequestKind::DistroLockGet {
            principal: principal.clone(),
        })
        .await?;
    match response {
        AdminResponseBody::DistroLock(lock) => Ok((*lock).map(from_provenance)),
        AdminResponseBody::Error(error) => Err(anyhow::anyhow!(error)),
        other => Err(anyhow::anyhow!(
            "unexpected distro lock response: {other:?}"
        )),
    }
}

/// Replace the target principal's durable distro record with an optimistic
/// compare-and-swap. A missing current record is an intentional create.
pub(crate) async fn write_lock_to_daemon(
    principal: &PrincipalId,
    lock: &DistroLock,
) -> anyhow::Result<()> {
    let mut client = crate::admin_client::connect_as_active_agent().await?;
    let current = client
        .request(AdminRequestKind::DistroLockGet {
            principal: principal.clone(),
        })
        .await?;

View on GitHub (pinned to affd8760f4)