dbt-labs/dbt-core · error · anyhow
unsupported pre-release lane {lane_str:?} in {semver:?}; acc
Error message
unsupported pre-release lane {lane_str:?} in {semver:?}; accepted: alpha, beta, rc, preview, dev What it means
parse_release_version only accepts pre-release lanes alpha, beta, rc, preview, dev. When the text before the dot in the pre-release suffix matches none of these lanes, this error is thrown listing the accepted values. It exists to keep the semver-to-PEP 440 mapping deterministic for PyPI.
Source
Thrown at crates/dbt-ci/src/release_version.rs:71
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(|_| ())
}
pub(crate) fn semver_to_pep440(semver: &str) -> Result<String> {View on GitHub (pinned to 0267ce9170)
Solutions
- Rename the pre-release lane to one of: alpha, beta, rc, preview, dev.
- Map custom lanes (e.g. nightly → dev) before passing the version in.
- If new lanes are genuinely needed, extend PreReleaseLane::parse rather than passing an unsupported lane.
Example fix
// before
let v = parse_release_version("1.2.3-nightly.7")?;
// after
let v = parse_release_version("1.2.3-dev.7")?; Defensive patterns
Strategy: validation
Validate before calling
ALLOWED_LANES = {"alpha", "beta", "rc", "preview", "dev"}
pre = version.split("-", 1)[-1].split(".", 1)[0]
assert pre in ALLOWED_LANES, f"lane {pre!r} not in {sorted(ALLOWED_LANES)}" Type guard
def has_supported_lane(v: str) -> bool:
return v.split("-", 1)[-1].split(".", 1)[0] in {"alpha", "beta", "rc", "preview", "dev"} Try / catch
match parse_release_version(&version) {
Err(e) if e.to_string().contains("unsupported pre-release lane") => map_custom_lane(&version),
other => other,
} Prevention
- Translate tool-specific lanes (nightly/snapshot) to dev/alpha before releasing
- Add a pre-commit or CI check on version strings
- Keep a single VERSION source of truth with lane validation
When it happens
Trigger: Calling parse_release_version / semver_to_pep440 / validate_release_version with an unknown lane such as `1.2.3-nightly.1`, `1.2.3-canary.3`, or `1.2.3-snapshot.0`.
Common situations: Teams using CI tools that emit `nightly` or `snapshot` pre-releases; porting conventions from npm (`next`, `canary`) into Python release tooling; typos like `alph.1`.
Related errors
- SemVer build metadata not supported in {semver:?}
- expected X.Y.Z, got {base:?} in {semver:?}
- expected integer after `{lane_str}.`, got {number:?} in {sem
- expected `<lane>.N` after `-`, got {pre:?} in {semver:?}
- formula file not found: {}
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/0212b5e30f606d6a.
Report an issue: GitHub.