dbt-labs/dbt-core · error · anyhow
expected `<lane>.N` after `-`, got {pre:?} in {semver:?}
Error message
expected `<lane>.N` after `-`, got {pre:?} in {semver:?} What it means
parse_release_version validates semver pre-release suffixes: after the `-`, the identifier must be `<lane>.N` where lane is one of alpha, beta, rc, preview, dev. This error fires when the pre-release string contains no dot, so no lane/number pair can be split. It guards conversion of semver versions to PEP 440 for PyPI publishing.
Source
Thrown at crates/dbt-ci/src/release_version.rs:69
None => (semver, None),
};
let parts: Vec<&str> = base.split('.').collect();
let well_formed = parts.len() == 3
&& parts
.iter()
.all(|p| !p.is_empty() && p.chars().all(|c| c.is_ascii_digit()));
if !well_formed {
bail!("expected X.Y.Z, got {base:?} in {semver:?}");
}
let Some(pre) = pre else {
return Ok(ParsedReleaseVersion {
base,
prerelease: None,
});
};
let (lane_str, number) = pre
.split_once('.')
.ok_or_else(|| anyhow!("expected `<lane>.N` after `-`, got {pre:?} in {semver:?}"))?;
let lane = PreReleaseLane::parse(lane_str).ok_or_else(|| {
anyhow!(
"unsupported pre-release lane {lane_str:?} in {semver:?}; \
accepted: alpha, beta, rc, preview, dev"
)
})?;
if number.is_empty() || !number.chars().all(|c| c.is_ascii_digit()) {
bail!("expected integer after `{lane_str}.`, got {number:?} in {semver:?}");
}
Ok(ParsedReleaseVersion {
base,
prerelease: Some((lane, number)),
})
}
pub(crate) fn validate_release_version(semver: &str) -> Result<()> {
parse_release_version(semver).map(|_| ())
}View on GitHub (pinned to 0267ce9170)
Solutions
- Change the version to the `<lane>.N` form, e.g. `1.2.3-beta` becomes `1.2.3-beta.0` or `1.2.3-rc.1`.
- Use only supported lanes: alpha, beta, rc, preview, dev.
- If the version comes from a script or git tag, update the generator to always append `.N` after the lane.
Example fix
// before
let v = parse_release_version("1.2.3-beta")?;
// after
let v = parse_release_version("1.2.3-beta.0")?; Defensive patterns
Strategy: validation
Validate before calling
import re
SEMVER_LANE = re.compile(r'^\d+\.\d+\.\d+-(alpha|beta|rc|preview|dev)\.\d+$')
assert SEMVER_LANE.match(version), f"{version} must be <major>.<minor>.<patch>-<lane>.N" Type guard
def is_lane_version(v: str) -> bool:
import re
return bool(re.match(r'^\d+\.\d+\.\d+-(alpha|beta|rc|preview|dev)\.\d+$', v)) Try / catch
match parse_release_version(&version) {
Err(e) if e.to_string().contains("`<lane>.N`") => bail!("use -alpha.0 style pre-release: {version}"),
other => other,
} Prevention
- Standardize release tags on the <lane>.N format in your release script
- Validate git tags with a CI regex before invoking release tooling
- Document accepted lanes (alpha, beta, rc, preview, dev) for the team
When it happens
Trigger: Calling parse_release_version (directly or via run, validate_release_version, or semver_to_pep440) with a version whose pre-release part after `-` lacks a `.N` suffix, e.g. `1.2.3-beta` or `1.2.3-rc`.
Common situations: Tagging releases as `v1.2.3-rc` from habit with other tooling; reading a version from git tags or env vars produced by scripts that drop the numeric component; mismatch between semver tooling that allows bare pre-release ids and this stricter lane format.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- unsupported pre-release lane {lane_str:?} in {semver:?}; acc
- SemVer build metadata not supported in {semver:?}
- expected X.Y.Z, got {base:?} in {semver:?}
- expected integer after `{lane_str}.`, got {number:?} in {sem
- no `{prefix}{version}-*.tar.gz` tarballs found in {source_de
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/ea3427736277c6d2.
Report an issue: GitHub.