dbt-labs/dbt-core · error · anyhow
expected integer after `{lane_str}.`, got {number:?} in {sem
Error message
expected integer after `{lane_str}.`, got {number:?} in {semver:?} What it means
For pre-release versions (X.Y.Z-lane.N), parse_release_version accepts only lanes alpha, beta, rc, preview, dev, and requires a non-empty integer after the lane's dot. This bail fires when the number portion after the lane is empty or contains non-digit characters.
Source
Thrown at crates/dbt-ci/src/release_version.rs:77
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> {
parse_release_version(semver).map(|p| p.to_pep440())
}
#[cfg(test)]
mod tests {
use super::*;View on GitHub (pinned to 0267ce9170)
Solutions
- Make the prerelease number a single non-negative integer, e.g. "1.2.3-rc.1".
- Ensure the lane is one of alpha, beta, rc, preview, dev (a different lane produces the preceding anyhow error).
- Normalize your version-generation tool to emit single-integer prerelease suffixes.
Example fix
// before
parse_release_version("1.2.3-rc.1.2")?;
// after
parse_release_version("1.2.3-rc.2")?; // collapse to single integer Defensive patterns
Strategy: validation
Validate before calling
fn validate_prerelease(v: &str) -> Result<(), String> {
if let Some((_, pre)) = v.split_once('-') {
let mut it = pre.splitn(2, '.');
let lane = it.next().unwrap_or("");
if !matches!(lane, "alpha"|"beta"|"rc"|"preview"|"dev") {
return Err(format!("unsupported lane {lane:?}"));
}
match it.next() {
Some(n) if !n.is_empty() && n.chars().all(|c| c.is_ascii_digit()) => Ok(()),
other => Err(format!("prerelease number must be an integer, got {other:?}")),
}
} else { Ok(()) }
} Try / catch
parse_release_version(v).map_err(|e| {
eprintln!("invalid prerelease in {v:?}: {e}; use e.g. 1.2.3-rc.1");
e
})?; Prevention
- Use single-integer prerelease suffixes: -alpha.1, -beta.2, -rc.1.
- Restrict version-generation tools to the accepted lanes.
- Run version validation as an early CI gate.
When it happens
Trigger: Calling parse_release_version with a prerelease like "1.2.3-alpha.", "1.2.3-beta.x", "1.2.3-rc.01a", or "1.2.3-rc.1.2" where the segment after 'rc.' is not a pure integer.
Common situations: Using SemVer dot-separated prerelease identifiers (e.g. -rc.1.2 or -alpha.beta) that this stricter scheme doesn't accept, typos in manually set versions, or versions generated by tools emitting multi-part prerelease numbers.
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
- SemVer build metadata not supported in {semver:?}
- expected X.Y.Z, got {base:?} in {semver:?}
- unsupported pre-release lane {lane_str:?} in {semver:?}; acc
- 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/c16a81739fab2068.
Report an issue: GitHub.