{"record":{"id":"14af0201829ddc3d","repo":"astrid-runtime/astrid","slug":"label-must-contain-exactly-targets","errorCode":null,"errorMessage":"{label} must contain exactly {} targets","messagePattern":"(.+?) must contain exactly (.+?) targets","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/update_channel.rs","lineNumber":341,"sourceCode":"\nfn canonical_time(value: &str, label: &str) -> anyhow::Result<DateTime<Utc>> {\n    let parsed = DateTime::parse_from_rfc3339(value)\n        .with_context(|| format!(\"signed channel {label} is not RFC3339\"))?\n        .with_timezone(&Utc);\n    ensure!(\n        parsed.to_rfc3339_opts(SecondsFormat::Secs, true) == value,\n        \"signed channel {label} is not canonical UTC RFC3339 seconds\"\n    );\n    Ok(parsed)\n}\n\nfn validate_targets_for(\n    targets: &[TargetMetadata],\n    expected_targets: &[&str],\n    version: &str,\n    label: &str,\n) -> anyhow::Result<()> {\n    ensure!(\n        targets.len() == expected_targets.len(),\n        \"{label} must contain exactly {} targets\",\n        expected_targets.len()\n    );\n    let mut seen = HashSet::new();\n    for target in targets {\n        ensure!(\n            expected_targets.contains(&target.triple.as_str())\n                && seen.insert(target.triple.as_str()),\n            \"{label} target set is invalid\"\n        );\n        let expected_asset = format!(\"astrid-{version}-{}.tar.gz\", target.triple);\n        ensure!(\n            target.asset == expected_asset\n                && target.sigstore_bundle == format!(\"{expected_asset}.sigstore.json\"),\n            \"signed metadata asset identity is invalid for {}\",\n            target.triple\n        );","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/update_channel.rs#L323-L359","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Regenerate the release/channel metadata with all expected targets present","Diff the targets array against expected_targets to find the missing/extra entry","Re-run the publish tooling instead of hand-editing the TOML metadata","Upgrade the CLI if a newer channel schema requires additional targets"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if targets.len() != expected_targets.len() {\n    return Err(format!(\"metadata has {} targets, expected {}\", targets.len(), expected_targets.len()));\n}","typeGuard":null,"tryCatchPattern":"match validate_targets(&targets, &expected, version, label) {\n    Ok(()) => proceed(),\n    Err(e) => republish_metadata_or_report(e),\n}","preventionTips":["Never hand-edit target lists in release metadata","Regenerate metadata via the publish tooling","Diff targets against the expected platform matrix before publishing"],"tags":["validation","target-list","update-channel"],"backgroundTag":"schema-validation-failed","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}