{"record":{"id":"c5254ad37672b3ac","repo":"astrid-runtime/astrid","slug":"distro-requires-ns-name-req-is-not-a-valid","errorCode":null,"errorMessage":"distro.requires.{ns}.{name} '{req}' is not a valid semver requirement","messagePattern":"distro\\.requires\\.(.+?)\\.(.+?) '(.+?)' is not a valid semver requirement","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/distro/validate.rs","lineNumber":113,"sourceCode":"    if semver::Version::parse(&manifest.distro.version).is_err() {\n        anyhow::bail!(\n            \"distro.version '{}' is not valid semver\",\n            manifest.distro.version,\n        );\n    }\n\n    // astrid-version is valid semver requirement (if set).\n    if let Some(ref av) = manifest.distro.astrid_version\n        && semver::VersionReq::parse(av).is_err()\n    {\n        anyhow::bail!(\"distro.astrid-version '{av}' is not a valid semver requirement\");\n    }\n\n    // Requires version strings are valid semver requirements.\n    for (ns, ifaces) in &manifest.distro.requires {\n        for (name, req) in ifaces {\n            if semver::VersionReq::parse(req).is_err() {\n                anyhow::bail!(\n                    \"distro.requires.{ns}.{name} '{req}' is not a valid semver requirement\",\n                );\n            }\n        }\n    }\n\n    // At least one capsule.\n    if manifest.capsules.is_empty() {\n        anyhow::bail!(\"distro must contain at least one capsule\");\n    }\n\n    // No duplicate capsule names, and each name must be a valid\n    // identifier. Names become path components in the `.shuttle` layout\n    // (`capsules/<name>.capsule`) and on disk under the capsule store;\n    // constraining them to `^[a-z][a-z0-9-]*$` keeps a manifest from\n    // introducing `/`, `..`, or other path-hostile characters there.\n    let mut seen_names = HashSet::new();\n    for cap in &manifest.capsules {","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/distro/validate.rs#L95-L131","documentation":"validate_manifest iterates `manifest.distro.requires` (namespace -> interface -> requirement) and bails if any requirement string fails `semver::VersionReq::parse`. These requirements declare which interface versions a distro consumes, so each must be a valid semver requirement. The namespace and interface names are included in the message to pinpoint the offending entry.","triggerScenarios":"A distro manifest with a `[distro.requires.<ns>]` entry whose version string is not a valid semver requirement — e.g. `api = \"1.0\"` (missing operator is actually valid; invalid ones are `\"v2\"`, `\"*.*\"`, `\"~1.2.3.4\"`, `\">= 1.x\"` typos, embedded whitespace).","commonSituations":"Typos when declaring interface requirements; pasting a git tag or commit-ish string; using Maven/npm-only version syntax not supported by the semver crate.","solutions":["Locate the `distro.requires.{ns}.{name}` entry named in the error and rewrite its value as a valid semver requirement (e.g. `^1.0`, `>=0.3, <0.5`).","Remove the entry if the requirement is unnecessary.","Check each requirement with a semver parser/regex before re-running validation."],"exampleFix":"# before\n[distro.requires.core]\nhttp = \"v2\"\n\n# after\n[distro.requires.core]\nhttp = \"^2.0\"","handlingStrategy":"validation","validationCode":"for (ns, ifaces) in &manifest.distro.requires {\n    for (name, req) in ifaces {\n        if semver::VersionReq::parse(req).is_err() {\n            eprintln!(\"bad requirement {ns}.{name} = '{req}'\");\n        }\n    }\n}","typeGuard":"fn is_semver_req(s: &str) -> bool {\n    semver::VersionReq::parse(s).is_ok()\n}","tryCatchPattern":"if let Err(e) = validate_manifest(&manifest) {\n    if e.to_string().contains(\"not a valid semver requirement\") {\n        // surface the offending ns.name from the message and correct the TOML\n    }\n}","preventionTips":["Use only semver operators supported by the semver crate (^, ~, =, >, <, >=, <=, *)","Never paste git tags or commit hashes into requires entries","Add a manifest linter to CI that parses every requirement"],"tags":["cli","manifest","semver","validation"],"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"}