astrid-runtime/astrid · error

must contain exactly targets

Error message

{label} must contain exactly {} targets

What it means

Validation of a target metadata list failed because the number of TargetMetadata entries does not equal the number of expected target triples. The library enforces an exact 1:1 count between shipped targets and the expected platform set for a given release or extension.

Solutions

  1. Regenerate the release/channel metadata with all expected targets present
  2. Diff the targets array against expected_targets to find the missing/extra entry
  3. Re-run the publish tooling instead of hand-editing the TOML metadata
  4. Upgrade the CLI if a newer channel schema requires additional targets
Defensive patterns

Strategy: validation

Validate before calling

if targets.len() != expected_targets.len() {
    return Err(format!("metadata has {} targets, expected {}", targets.len(), expected_targets.len()));
}

Try / catch

match validate_targets(&targets, &expected, version, label) {
    Ok(()) => proceed(),
    Err(e) => republish_metadata_or_report(e),
}

Prevention

When it happens

Trigger: Calling validate_targets / verify_release_extension with a targets slice whose length differs from expected_targets.len() — e.g. a release metadata file lists 2 targets where 3 are required, or a target was dropped during publishing.

Common situations: A maintainer edited release metadata by hand and removed/added a target; a publishing script produced a partial target list; an old channel format missing newer required targets.

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/14af0201829ddc3d. Report an issue: GitHub.

Appendix: source

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

fn canonical_time(value: &str, label: &str) -> anyhow::Result<DateTime<Utc>> {
    let parsed = DateTime::parse_from_rfc3339(value)
        .with_context(|| format!("signed channel {label} is not RFC3339"))?
        .with_timezone(&Utc);
    ensure!(
        parsed.to_rfc3339_opts(SecondsFormat::Secs, true) == value,
        "signed channel {label} is not canonical UTC RFC3339 seconds"
    );
    Ok(parsed)
}

fn validate_targets_for(
    targets: &[TargetMetadata],
    expected_targets: &[&str],
    version: &str,
    label: &str,
) -> anyhow::Result<()> {
    ensure!(
        targets.len() == expected_targets.len(),
        "{label} must contain exactly {} targets",
        expected_targets.len()
    );
    let mut seen = HashSet::new();
    for target in targets {
        ensure!(
            expected_targets.contains(&target.triple.as_str())
                && seen.insert(target.triple.as_str()),
            "{label} target set is invalid"
        );
        let expected_asset = format!("astrid-{version}-{}.tar.gz", target.triple);
        ensure!(
            target.asset == expected_asset
                && target.sigstore_bundle == format!("{expected_asset}.sigstore.json"),
            "signed metadata asset identity is invalid for {}",
            target.triple
        );

View on GitHub (pinned to affd8760f4)