unicity-aos/aos-ce · error

[package].version = " " is not MAJOR.MINOR.PATCH.

Error message

[package].version = "{v}" is not MAJOR.MINOR.PATCH.

What it means

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.

Solutions

  1. Change the version to exactly three numeric parts, e.g. `version = "0.1.0"`.
  2. Remove prefixes like `v` and suffixes like `-beta` if the linter still rejects the value.
  3. Bump MAJOR.MINOR.PATCH per your release process going forward.

Example fix

// before
[package]
version = "1.0"

// after
[package]
version = "1.0.0"
Defensive patterns

Strategy: validation

Validate before calling

// Rust
let v = root["package"]["version"].as_str().unwrap_or_default();
let parts: Vec<_> = v.split('.').collect();
if parts.len() != 3 || parts.iter().any(|p| p.parse::<u64>().is_err()) {
    return Err(format!("version {v} is not MAJOR.MINOR.PATCH"));
}

Prevention

When it happens

Trigger: Setting `version = "1.0"`, `version = "v1.0.0"`, `version = "1.0.0-beta"` or any non x.y.z numeric value in [package].

Common situations: 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.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/0dd71eb8355fbf31. Report an issue: GitHub.

Appendix: source

Thrown at capsules/capsule-forge/src/checks.rs:150

        out.push(Finding::info(
            "The `kv` capability field is reserved; ordinary capsule KV does not require it.",
            "Omit `kv` unless the pinned runtime contract specifically requires it.",
        ));
    }
}

fn check_package(root: &Toml, out: &mut Vec<Finding>) {
    let pkg = root.get("package");
    let name = pkg.and_then(|p| p.get("name")).and_then(Toml::as_str);
    if name.is_none_or(str::is_empty) {
        out.push(Finding::err(
            "[package].name is missing or empty.",
            "Add `name = \"my-capsule\"` under [package].",
        ));
    }
    match pkg.and_then(|p| p.get("version")).and_then(Toml::as_str) {
        Some(v) if is_semverish(v) => {}
        Some(v) => out.push(Finding::err(
            format!("[package].version = \"{v}\" is not MAJOR.MINOR.PATCH."),
            "Use a three-part numeric version like \"0.1.0\".",
        )),
        None => out.push(Finding::err(
            "[package].version is missing.",
            "Add `version = \"0.1.0\"` under [package].",
        )),
    }
}

fn check_component(root: &Toml, out: &mut Vec<Finding>) {
    let comps = root.get("component").and_then(Toml::as_array);
    let has_file = comps.is_some_and(|arr| {
        arr.iter().any(|c| {
            c.get("file")
                .and_then(Toml::as_str)
                .is_some_and(|f| !f.is_empty())
        })

View on GitHub (pinned to f6f22024fb)