astrid-runtime/astrid · error

durable capsule {id} failed byte-for-byte readback

Error message

durable capsule {id} failed byte-for-byte readback

What it means

After installing the migrated package into the durable registry, migration reads the snapshot back and compares it byte-for-byte with what was written. A mismatch means the durable store did not faithfully persist the package — an internal consistency failure — so migration aborts.

Source

Thrown at crates/astrid-capsule-install/src/storage/migration.rs:185

        verification
            .content_digest()
            .clone_into(&mut durable_authority.content_digest);
        let durable_authority_bytes = serde_json::to_vec_pretty(&durable_authority)
            .with_context(|| format!("serialize durable legacy capsule authority {id}"))?;
        let package = CapsulePackage::new(archive, meta_bytes, durable_authority_bytes);
        let expectation = match registry.get_snapshot(&owner, id)? {
            None => CapsuleInstallExpectation::Absent,
            Some(snapshot) if snapshot.package() == &package => {
                CapsuleInstallExpectation::Generation(snapshot.generation())
            },
            Some(_) => bail!("durable capsule {id} conflicts with legacy native content"),
        };
        registry.install(&owner, id, &package, expectation)?;
        let readback = registry
            .get_snapshot(&owner, id)?
            .ok_or_else(|| anyhow::anyhow!("durable capsule {id} disappeared after publish"))?;
        if readback.package() != &package {
            bail!("durable capsule {id} failed byte-for-byte readback");
        }
        read_verified_durable_package_for_owner(store, &owner, id)?.ok_or_else(|| {
            anyhow::anyhow!("durable capsule {id} failed authoritative verification")
        })?;
        astrid_core::platform_fs::verify_no_redirects(&target)
            .with_context(|| format!("verify legacy capsule {id} before retirement"))?;
        let final_archive = canonical_legacy_archive(home, &target, &meta, &manifest)?;
        if final_archive != package.archive {
            bail!("legacy capsule {id} changed before retirement");
        }
        if fs::read(target.join("meta.json"))? != package.metadata {
            bail!("legacy capsule {id} metadata changed before retirement");
        }
        if read_installed_authority_bytes(home, &target)?.as_deref()
            != Some(source_authority_bytes.as_slice())
        {
            bail!("legacy capsule {id} authority changed before retirement");
        }

View on GitHub (pinned to affd8760f4)

Solutions

  1. Re-run migration (the install is transactional and can be retried)
  2. Verify/repair the durable store's integrity (checksums, fsck-like validation)
  3. Ensure no other process writes to the store concurrently during migration
  4. Report as a store bug if it reproduces on a healthy, quiescent store

Example fix

// before
migrate_all_native_capsules(store)  // concurrent writer active
// after
stop other astrid processes; then migrate_all_native_capsules(store)
Defensive patterns

Strategy: retry

Validate before calling

// check store health and quiescence before migrating
if other_astrid_processes_running() { return Err("stop concurrent writers"); }
// optionally verify an existing durable capsule's checksums before migration

Try / catch

match migrate_native_capsules(home, store) {
    Err(e) if e.to_string().contains("failed byte-for-byte readback") => {
        eprintln!("store write not durable or corrupted; verify store and retry");
    }
    other => other?,
}

Prevention

When it happens

Trigger: The durable registry returned a snapshot whose package bytes differ from the installed CapsulePackage; storage corruption or a buggy/concurrent writer modified the stored package between install and readback.

Common situations: Corrupted store directory; another process writing the same capsule concurrently; disk/cache issues in the durable store.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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