astrid-runtime/astrid · error

legacy capsule authority identity differs for {id}

Error message

legacy capsule authority identity differs for {id}

What it means

After verifying the installed authority receipt, migration checks that the receipt's capsule_id and version match the capsule being migrated. A mismatch means the pinned authority belongs to a different capsule or version, so migration refuses to publish it durably.

Source

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

        let meta: CapsuleMeta = serde_json::from_slice(&meta_bytes)
            .with_context(|| format!("decode legacy capsule metadata {id}"))?;
        if meta.version != manifest.package.version {
            bail!("legacy capsule metadata version differs for {id}");
        }
        // Released pre-authority installs are admitted only through the
        // existing one-time verifier. It pins their exact manifest,
        // capabilities, and executable before any durable publication.
        // Relocated homes keep receipts hashed from a previous absolute
        // path; rebind a unique leftover onto this target first.
        rebind_relocated_legacy_authority_receipt(home, &target, &manifest, workspace_targets)
            .with_context(|| format!("rebind relocated leftover authority for {id}"))?;
        verify_installed_authority(home, &target, &manifest)
            .with_context(|| format!("verify legacy capsule authority {id}"))?;
        let authority = read_installed_authority(home, &target)?.ok_or_else(|| {
            anyhow::anyhow!("legacy capsule {id} authority verification produced no receipt")
        })?;
        if authority.capsule_id != id || authority.version != manifest.package.version {
            bail!("legacy capsule authority identity differs for {id}");
        }
        let source_authority_bytes = read_installed_authority_bytes(home, &target)?
            .ok_or_else(|| anyhow::anyhow!("legacy capsule {id} authority receipt disappeared"))?;
        let archive = canonical_legacy_archive(home, &target, &meta, &manifest)?;
        let verification = artifact::verify_archive_bytes(&archive)
            .with_context(|| format!("verify canonical legacy capsule archive {id}"))?;
        let mut durable_authority = authority;
        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())
            },

View on GitHub (pinned to affd8760f4)

Solutions

  1. Regenerate/re-verify the authority receipt for this capsule so it carries the correct id and version
  2. Restore the original manifest id/version that the receipt was issued for
  3. Remove the stale receipt and reinstall the capsule through the normal verifier
  4. Delete the mismatched install directory if it is a leftover

Example fix

// before
receipt: capsule_id="old-name", version="1.0.0"; dir/manifest: "new-name" 1.1.0
// after
re-run authority verification for "new-name" 1.1.0 so the receipt matches
Defensive patterns

Strategy: validation

Validate before calling

fn receipt_matches(capsule_dir: &Path) -> Result<(), String> {
    let receipt = read_installed_authority(home, capsule_dir)?
        .ok_or("no authority receipt")?;
    let id = capsule_dir.file_name().unwrap().to_string_lossy().to_string();
    let manifest = astrid_capsule::discovery::load_manifest(&capsule_dir.join("Capsule.toml")).map_err(|e| e.to_string())?;
    if receipt.capsule_id != id || receipt.version != manifest.package.version {
        return Err("receipt identity mismatch".into());
    }
    Ok(())
}

Try / catch

if let Err(e) = migrate_native_capsules(home, store) {
    if e.to_string().contains("authority identity differs") {
        eprintln!("regenerate or restore the matching authority receipt, then retry");
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: The authority receipt on disk was written for a different id/version — e.g. a capsule was renamed or re-versioned in place, or receipts were copied between installs.

Common situations: Hand-copied receipt files between capsule directories; editing the manifest name/version without regenerating the authority receipt; restored backups mixing receipts.

Related errors


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