astrid-runtime/astrid · error

legacy capsule metadata version differs for {id}

Error message

legacy capsule metadata version differs for {id}

What it means

The legacy capsule's meta.json records an installed version that must agree with the version in Capsule.toml. If serde-decoded meta.version differs from manifest.package.version, the install is internally inconsistent and migration aborts for that capsule.

Source

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

        }
        let id = target
            .file_name()
            .and_then(|name| name.to_str())
            .ok_or_else(|| anyhow::anyhow!("legacy capsule entry has a non-UTF-8 name"))?;
        let manifest = astrid_capsule::discovery::load_manifest(&target.join("Capsule.toml"))
            .with_context(|| format!("read legacy capsule manifest {id}"))?;
        if manifest.package.name != id {
            bail!(
                "legacy capsule directory {id} does not match manifest id {}",
                manifest.package.name
            );
        }
        let meta_bytes = fs::read(target.join("meta.json"))
            .with_context(|| format!("read legacy capsule metadata {id}"))?;
        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"))?;

View on GitHub (pinned to affd8760f4)

Solutions

  1. Reinstall the capsule so meta.json and Capsule.toml are regenerated consistently
  2. Update meta.json's version to match the manifest only if you are certain the install matches
  3. Delete the inconsistent install and migrate a clean copy
  4. Restore both files from the same backup generation

Example fix

// before (meta.json)
{"version": "1.0.0"}  // Capsule.toml says 1.2.0
// after
reinstall capsule so meta.json records 1.2.0
Defensive patterns

Strategy: validation

Validate before calling

fn versions_agree(capsule_dir: &Path) -> Result<(), String> {
    let manifest = astrid_capsule::discovery::load_manifest(&capsule_dir.join("Capsule.toml")).map_err(|e| e.to_string())?;
    let meta: CapsuleMeta = serde_json::from_slice(&std::fs::read(capsule_dir.join("meta.json")).map_err(|e| e.to_string())?)
        .map_err(|e| e.to_string())?;
    if meta.version != manifest.package.version { return Err("meta/manifest version mismatch".into()); }
    Ok(())
}

Try / catch

if let Err(e) = migrate_native_capsules(home, store) {
    if e.to_string().contains("metadata version differs") {
        eprintln!("reinstall the capsule so meta.json matches Capsule.toml, then retry");
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: meta.json was written for an older/newer install than the current Capsule.toml; the manifest was upgraded without reinstalling; a partial update overwrote one of the two files.

Common situations: Manually replacing Capsule.toml with a newer version during development; interrupted upgrade leaving stale meta.json; restored backup mixing file generations.

Related errors


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