{"record":{"id":"0dd71eb8355fbf31","repo":"unicity-aos/aos-ce","slug":"package-version-v-is-not-major-minor-patch","errorCode":null,"errorMessage":"[package].version = \"{v}\" is not MAJOR.MINOR.PATCH.","messagePattern":"\\[package\\]\\.version = \"(.+?)\" is not MAJOR\\.MINOR\\.PATCH\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"capsules/capsule-forge/src/checks.rs","lineNumber":150,"sourceCode":"        out.push(Finding::info(\n            \"The `kv` capability field is reserved; ordinary capsule KV does not require it.\",\n            \"Omit `kv` unless the pinned runtime contract specifically requires it.\",\n        ));\n    }\n}\n\nfn check_package(root: &Toml, out: &mut Vec<Finding>) {\n    let pkg = root.get(\"package\");\n    let name = pkg.and_then(|p| p.get(\"name\")).and_then(Toml::as_str);\n    if name.is_none_or(str::is_empty) {\n        out.push(Finding::err(\n            \"[package].name is missing or empty.\",\n            \"Add `name = \\\"my-capsule\\\"` under [package].\",\n        ));\n    }\n    match pkg.and_then(|p| p.get(\"version\")).and_then(Toml::as_str) {\n        Some(v) if is_semverish(v) => {}\n        Some(v) => out.push(Finding::err(\n            format!(\"[package].version = \\\"{v}\\\" is not MAJOR.MINOR.PATCH.\"),\n            \"Use a three-part numeric version like \\\"0.1.0\\\".\",\n        )),\n        None => out.push(Finding::err(\n            \"[package].version is missing.\",\n            \"Add `version = \\\"0.1.0\\\"` under [package].\",\n        )),\n    }\n}\n\nfn check_component(root: &Toml, out: &mut Vec<Finding>) {\n    let comps = root.get(\"component\").and_then(Toml::as_array);\n    let has_file = comps.is_some_and(|arr| {\n        arr.iter().any(|c| {\n            c.get(\"file\")\n                .and_then(Toml::as_str)\n                .is_some_and(|f| !f.is_empty())\n        })","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/capsules/capsule-forge/src/checks.rs#L132-L168","documentation":"When `[package].version` exists but fails `is_semverish` (not three dot-separated numeric parts), `check_package` emits this error showing the offending value. Capsules require MAJOR.MINOR.PATCH versioning so builds can be compared and upgraded deterministically.","triggerScenarios":"Setting `version = \"1.0\"`, `version = \"v1.0.0\"`, `version = \"1.0.0-beta\"` or any non x.y.z numeric value in [package].","commonSituations":"Using a leading `v` out of habit from git tags, dropping the patch segment, or carrying over a Cargo-style version with pre-release/build metadata the linter rejects.","solutions":["Change the version to exactly three numeric parts, e.g. `version = \"0.1.0\"`.","Remove prefixes like `v` and suffixes like `-beta` if the linter still rejects the value.","Bump MAJOR.MINOR.PATCH per your release process going forward."],"exampleFix":"// before\n[package]\nversion = \"1.0\"\n\n// after\n[package]\nversion = \"1.0.0\"","handlingStrategy":"validation","validationCode":"// Rust\nlet v = root[\"package\"][\"version\"].as_str().unwrap_or_default();\nlet parts: Vec<_> = v.split('.').collect();\nif parts.len() != 3 || parts.iter().any(|p| p.parse::<u64>().is_err()) {\n    return Err(format!(\"version {v} is not MAJOR.MINOR.PATCH\"));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use a release tool that stamps semver versions automatically.","Strip `v` prefixes and pre-release suffixes from manifest versions.","Remember the manifest wants exactly three numeric parts."],"tags":["toml","versioning","format-validation","config"],"backgroundTag":"invalid-date-format","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}