vectordotdev/vector · error

version ' ' has prerelease or build metadata; only plain…

Error message

version '{s}' has prerelease or build metadata; only plain X.Y.Z is allowed

What it means

parse_strict_release parses a version string with semver::Version::parse but additionally rejects versions carrying prerelease (e.g. -alpha.1) or build metadata (e.g. +build.5). This mirrors the repository's release-tag convention of plain `vX.Y.Z` tags, so any non-plain version is treated as invalid input for release-based validation and sorting.

Solutions

  1. Change the version string to a plain three-component release, e.g. "0.45.0-rc.1" → "0.45.0"
  2. Drop build metadata (everything from `+` onward) and any `-prerelease` suffix
  3. If a prerelease genuinely must be referenced, use the eventual final release version it shipped in

Example fix

// before
let v = parse_strict_release("0.45.0-rc.1")?;
// after
let v = parse_strict_release("0.45.0")?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_plain_release(s: &str) -> bool {
    semver::Version::parse(s).map(|v| v.pre.is_empty() && v.build.is_empty()).unwrap_or(false)
}
assert!(is_plain_release("0.45.0"));

Prevention

When it happens

Trigger: Calling parse_strict_release (directly or via sort_enacted/validate_enacted) with strings like "0.45.0-rc.1", "1.2.3+build", or any X.Y.Z-suffix form instead of a bare "X.Y.Z".

Common situations: A deprecation entry referencing a release candidate or nightly build as its removed_in/deprecated_since version; copy-pasting a version from Cargo/semver output that included build metadata; typo-ed version strings pulled from non-release tags.

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/0dcc0fc914a3d0f0. Report an issue: GitHub.

Appendix: source

Thrown at vdev/src/utils/deprecation.rs:409

            );
        }
    }
    Ok(enacted.len())
}

/// True when `a` is in a later major.minor release than `b`. Equal or smaller
/// major.minor (regardless of patch) returns false.
pub fn later_minor(a: &Version, b: &Version) -> bool {
    (a.major, a.minor) > (b.major, b.minor)
}

/// Parse a release version string strictly: only plain `X.Y.Z` is allowed
/// (no prerelease or build metadata). Mirrors the rule that release tags
/// follow `vX.Y.Z`.
pub fn parse_strict_release(s: &str) -> Result<Version> {
    let v = Version::parse(s)?;
    if !v.pre.is_empty() || !v.build.is_empty() {
        bail!("version '{s}' has prerelease or build metadata; only plain X.Y.Z is allowed");
    }
    Ok(v)
}

/// Render the JSON that `sync_deprecations_cue` would write, without
/// touching disk. Returns the serialized string (with trailing newline) so
/// callers can compare against the on-disk file.
pub fn rendered_json(repo_root: &Path) -> Result<String> {
    let dir = repo_root.join(DEPRECATION_DIR);
    let pending = read_deprecation_fragments(&dir)?;
    let mut data = read_json(repo_root)?;
    sort_enacted(&mut data.deprecations_enacted);
    data.deprecations_pending = pending_excluding_enacted(&pending, &data.deprecations_enacted);
    Ok(serde_json::to_string_pretty(&data)? + "\n")
}

/// Regenerate `DEPRECATIONS_JSON` from `deprecation.d/` (pending) plus the
/// existing enacted entries already in the file.

View on GitHub (pinned to bdb87aeaa4)