astrid-runtime/astrid · error

release metadata identity is invalid

Error message

{label} release metadata identity is invalid

What it means

This error is thrown by verify_release_extension when the parsed release-extension TOML metadata has an identity that does not match what the updater requires: schema_version must be 1, kind must equal the expected extension kind ("musl" or "Windows"), and product/repository must equal the built-in PRODUCT and REPOSITORY constants. It is a supply-chain integrity check that ensures the downloaded metadata file actually describes this product's release format before any hash or version data from it is trusted.

Solutions

  1. Regenerate the release extension metadata with the current release tooling so schema_version=1 and kind/product/repository match the constants in update_channel.rs
  2. Verify the downloaded metadata asset comes from the authenticated release for PRODUCT/REPOSITORY and was not substituted by a mirror or proxy cache
  3. Check you are passing the right metadata file to the right verifier (musl metadata to verify_musl_extension, Windows metadata to verify_windows_extension)
  4. If you fork the product, update the PRODUCT/REPOSITORY constants or the publishing pipeline to emit matching identity fields

Example fix

// before: channel config pointing at a fork's extension metadata
channel = "https://mirror.example.com/fork/astrid-release-musl-extension.toml"
// after: use the official product's extension metadata
channel = "https://releases.astrid.dev/stable/astrid-release-musl-extension.toml"
Defensive patterns

Strategy: validation

Validate before calling

fn metadata_identity_ok(text: &str, product: &str, repository: &str, kind: &str) -> bool {
    match text.parse::<toml::Table>() {
        Ok(t) => t.get("schema_version").and_then(|v| v.as_integer()) == Some(1)
            && t.get("kind").and_then(|v| v.as_str()) == Some(kind)
            && t.get("product").and_then(|v| v.as_str()) == Some(product)
            && t.get("repository").and_then(|v| v.as_str()) == Some(repository),
        Err(_) => false,
    }
}

Type guard

fn is_valid_extension(e: &ReleaseExtension, expected_kind: &str) -> bool {
    e.schema_version == 1 && e.kind == expected_kind
}

Try / catch

match verify_musl_extension(&bytes, &manifest, &pointer, target) {
    Ok(blake3) => proceed(blake3),
    Err(e) if e.to_string().contains("identity is invalid") => {
        eprintln!("metadata does not belong to this product/schema; refusing update");
        abort_update();
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling resolve_target_blake3, verify_musl_extension, or verify_windows_extension with bytes of a metadata file whose TOML parses but has schema_version != 1, a kind field not matching the expected extension kind, or product/repository fields differing from PRODUCT/REPOSITORY (e.g. a metadata file for a different repo or an older schema).

Common situations: Pointing the update channel at a third-party fork whose release extensions declare a different repository; serving stale extension metadata generated by an older schema_version; accidentally substituting a musl metadata file where the Windows extension is verified (kind mismatch); hand-edited release metadata.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at crates/astrid-cli/src/commands/update_channel.rs:656

#[allow(clippy::too_many_arguments)]
fn verify_release_extension(
    bytes: &[u8],
    legacy_manifest_bytes: &[u8],
    pointer: &ChannelPointer,
    target: &str,
    expected_kind: &str,
    expected_targets: &[&str],
    label: &str,
) -> anyhow::Result<String> {
    ensure!(
        expected_targets.contains(&target),
        "{label} release metadata does not support target '{target}'"
    );
    let text = std::str::from_utf8(bytes)
        .with_context(|| format!("{label} release metadata is not UTF-8"))?;
    let extension: ReleaseExtension = toml::from_str(text)
        .with_context(|| format!("{label} release metadata is invalid TOML"))?;
    ensure!(
        extension.schema_version == 1
            && extension.kind == expected_kind
            && extension.product == PRODUCT
            && extension.repository == REPOSITORY,
        "{label} release metadata identity is invalid"
    );
    canonical_version(&extension.version)?;
    ensure!(
        extension.version == pointer.release.version
            && extension.tag == pointer.release.tag
            && extension.source_commit == pointer.release.source_commit
            && extension.release_workflow_identity == pointer.release.release_workflow_identity,
        "{label} release metadata does not match the authenticated legacy release"
    );
    ensure!(
        extension.legacy_release.metadata_asset == pointer.release.metadata_asset
            && extension.legacy_release.metadata_blake3 == pointer.release.metadata_blake3
            && blake3::hash(legacy_manifest_bytes).to_hex().as_str()

View on GitHub (pinned to affd8760f4)