{"record":{"id":"aefdd14b16a41c6e","repo":"astrid-runtime/astrid","slug":"distro-astrid-version-req-is-not-a-valid-requi","errorCode":null,"errorMessage":"distro.astrid-version {req:?} is not a valid requirement: {e}","messagePattern":"distro\\.astrid-version (.+?) is not a valid requirement: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/distro/validate.rs","lineNumber":304,"sourceCode":"/// **Prerelease policy.** By default `semver::VersionReq::matches` refuses a\n/// prerelease running version (e.g. `0.6.0-dev.3` does *not* satisfy `>=0.6.0`),\n/// which would falsely reject a locally-built / dev CLI that is, by release\n/// triple, at or above the floor. That is the classic semver footgun. When the\n/// requirement is a plain release floor we compare on the **release triple\n/// only** — the running version's `(major, minor, patch)` with the prerelease\n/// and build metadata stripped — so a dev build of a sufficiently-new astrid is\n/// accepted, while still rejecting a CLI whose release triple genuinely falls\n/// below the floor. A clean (non-prerelease) running version compares unchanged.\n///\n/// **When the requirement itself names a prerelease** (e.g. `>=0.6.0-rc.3`) the\n/// operator is deliberately gating on a specific prerelease, so triple-stripping\n/// the running version would *over-accept*: `0.6.0-rc.2` would be lifted to\n/// `0.6.0` and wrongly satisfy `>=0.6.0-rc.3`. In that case we drop the\n/// dev-build convenience and compare the running version **as-is** under exact\n/// semver semantics, so prerelease ordering (`rc.2 < rc.3`) is honoured.\npub(crate) fn distro_astrid_version_satisfied(req: &str, running: &Version) -> anyhow::Result<()> {\n    let version_req = VersionReq::parse(req).map_err(|e| {\n        anyhow::anyhow!(\"distro.astrid-version {req:?} is not a valid requirement: {e}\")\n    })?;\n\n    // If any comparator in the requirement carries a prerelease, the operator\n    // is gating on an exact prerelease — honour real semver semantics (no\n    // triple-strip) so a lower prerelease of the same triple is not lifted past\n    // the floor. Otherwise apply the dev-build footgun fix below.\n    let req_names_prerelease = version_req.comparators.iter().any(|c| !c.pre.is_empty());\n    if req_names_prerelease {\n        if version_req.matches(running) {\n            return Ok(());\n        }\n        return Err(AstridVersionTooOld {\n            req: req.to_string(),\n            running: running.to_string(),\n        }\n        .into());\n    }\n","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/distro/validate.rs#L286-L322","documentation":"distro_astrid_version_satisfied parses the manifest's [distro].astrid-version string as a semver::VersionReq before evaluating it against the running version. This error means the requirement string itself is not a valid semver requirement — it never reaches any comparison logic.","triggerScenarios":"A Distro.toml declaring astrid-version values like '>= 0.6' with bad spacing variants the parser rejects, '0.6.x' wildcard syntax not accepted, '^0.6.0' if caret is unsupported, multiple comparators with a typo ('>=0.5, <0.7' with wrong separator), or an empty string.","commonSituations":"Authors copying npm-style ranges ('~0.6.2', 'x-bounds') that the Rust semver crate rejects; typos like '>=o.6.0'; listing two versions separated by spaces incorrectly.","solutions":["Rewrite astrid-version using semver requirement syntax the crate accepts (e.g. '>=0.6.0', '0.6.0', '>=0.5, <0.7').","Drop npm-specific operators (~, ^, x-ranges) not supported by the semver crate.","Test the requirement string with a quick `VersionReq::parse` check or cargo script before committing the manifest."],"exampleFix":"# before (Distro.toml)\n[distro]\nastrid-version = \"^0.6.0\"\n# after\n[distro]\nastrid-version = \">=0.6.0\"","handlingStrategy":"validation","validationCode":"fn is_valid_semver_req(s: &str) -> bool { semver::VersionReq::parse(s).is_ok() }\n// check the [distro].astrid-version string before publishing","typeGuard":null,"tryCatchPattern":"match enforce_astrid_version(&manifest) {\n    Err(e) if e.to_string().contains(\"not a valid requirement\") => {\n        eprintln!(\"fix astrid-version syntax in Distro.toml: {e}\");\n    },\n    other => other?,\n}","preventionTips":["Use only semver-crate syntax (comparators like >=0.6.0, exact versions).","Avoid npm-isms: ~, ^, x-ranges.","Unit-test requirement strings before releasing a manifest."],"tags":["semver","config","validation","manifest"],"backgroundTag":"invalid-config-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}