#1944·astrid

Migration barrier flattens anyhow chains, hiding the real boot failure cause

Author: jvsteinerCreated Sep 15, 2026Updated Sep 15, 2026

Summary

Boot failures in the legacy migration barrier are reported with {error} rather than {error:#}, so only the outermost anyhow context reaches the log. Every .with_context(...) frame underneath — which is where the actual cause lives — is discarded. Diagnosing a failed upgrade currently requires reading the source and inspecting on-disk state by hand.

Mechanism

crates/astrid-kernel/src/legacy_migration_barrier/mod.rs:345:

rust
let capsule_report =
    migrate_all_native_capsules_with_report(&Arc::new(store.clone()), home, directory)
        .map_err(|error| {
            io::Error::other(format!("legacy capsule migration failed: {error}"))
        })?;

anyhow::Error's Display prints only the top context. The producing code builds a deliberately informative chain — crates/astrid-capsule-install/src/storage/migration.rs:145:

rust
verify_installed_authority(home, &target, &manifest)
    .with_context(|| format!("verify legacy capsule authority {id}"))?;

and verify_installed_authority (crates/astrid-capsule-install/src/authority.rs:533) bails with a message that names the exact discrepancy:

rust
bail!(
    "installed capsule identity/version differs from its authority receipt (approved {} {}, found {} {})",
    authority.capsule_id, authority.version,
    manifest.package.name, manifest.package.version
);

None of that survives. What reaches daemon-boot.log is:

Error: Failed to boot Kernel: legacy capsule migration failed: verify legacy capsule authority astrid-capsule-agents

That names the capsule but not the problem — it is indistinguishable from a missing WASM, a capability expansion, a manifest digest mismatch, or a schema version bump, all of which are separate bail!s in the same function.

To recover the real cause I had to read authority.rs, locate the receipt by grepping etc/capsule-authority/*.json for the capsule id, and compare it against the manifest by hand:

etc/capsule-authority/832eed9e….json  ->  "version": "0.1.0"
home/default/.local/capsules/astrid-capsule-agents/Capsule.toml  ->  version = "0.2.0"

The receipt was stale — the capsule updated 0.1.0 → 0.2.0 on 2026-09-05 but the receipt still dated 2026-07-24. That one line of output would have been the whole diagnosis. Across my install, 8 of 19 capsules were in this state (agents, context-engine, fs, memory, prompt-builder, react, router, system).

Reproduction Steps

  1. Put any capsule into a state that trips a bail! inside verify_installed_authority — e.g. update a capsule's Capsule.toml version without refreshing its receipt under etc/capsule-authority/.
  2. Run astrid start.
  3. Read ~/.astrid/log/daemon-boot.log.
  4. Observe only verify legacy capsule authority <id>, with no indication of which of the five failure modes occurred.

Expected Behavior

  • Format anyhow errors crossing this boundary with the alternate selector ({error:#}) so the full context chain is preserved, or attach the source via a typed error rather than flattening to a string.
  • Apply the same treatment to the sibling io::Error::other(format!(...)) conversions in the barrier; this call site is the one I hit, not necessarily the only one.
  • Since these paths only run during upgrade, where the operator has no other signal, err toward more context rather than less.

Environment

  • OS: macOS 15.6 (Darwin 24.6.0), arm64
  • Astrid: 2026.9.2, installed via astrid update
  • Source: astrid-runtime/astrid @ 73661c9b (Cargo version 0.10.4)
  • 19 native capsules under home/default/.local/capsules/, 8 with stale authority receipts

Logs / Backtrace

What was logged:

Error: Failed to boot Kernel: legacy capsule migration failed: verify legacy capsule authority astrid-capsule-agents

What the chain actually contained (recovered by hand):

legacy capsule migration failed
  -> verify legacy capsule authority astrid-capsule-agents
    -> installed capsule identity/version differs from its authority receipt
       (approved astrid-capsule-agents 0.1.0, found astrid-capsule-agents 0.2.0)