dbt-labs/dbt-core · error · anyhow
{filename} declares Requires-Python {actual:?} but the sdist
Error message
{filename} declares Requires-Python {actual:?} but the sdist says {expected:?}; point `--pyproject-dir` at the pyproject that built these wheels What it means
The wheel's METADATA Requires-Python does not exactly match the requires-python derived from the sdist's pyproject. This guard exists to catch stale or mismatched wheels — usually wheels built from a different pyproject than the one supplied via --pyproject-dir.
Source
Thrown at crates/dbt-ci/src/sdist.rs:151
/// points at, in either direction. pip survives such a mismatch (it builds the
/// wheel and reads the real metadata), but uv trusts the sdist's PKG-INFO and
/// never re-checks — so a wrong `Requires-Python` installs on an unsupported
/// interpreter and dies at import on an ABI symbol, and a missing `Requires-Dist`
/// (in either direction) installs the wrong dependency set and dies on first run.
fn check_wheel_metadata_agrees(spec: &Spec, filename: &str, wheel: &[u8]) -> Result<()> {
let Some(metadata) = wheel_metadata(wheel)
.with_context(|| format!("read METADATA from {filename}"))?
.map(|raw| Metadata::parse(&raw))
.transpose()
.with_context(|| format!("parse METADATA from {filename}"))?
else {
bail!("{filename} has no *.dist-info/METADATA");
};
let expected_python = spec.requires_python.as_deref();
let actual_python = metadata.requires_python.as_deref();
if actual_python != expected_python {
bail!(
"{filename} declares Requires-Python {actual:?} but the sdist says \
{expected:?}; point `--pyproject-dir` at the pyproject that built \
these wheels",
actual = actual_python.unwrap_or("(absent)"),
expected = expected_python.unwrap_or("(absent)"),
);
}
let expected_deps: std::collections::BTreeSet<&str> =
spec.dependencies.iter().map(|d| d.trim()).collect();
let actual_deps: std::collections::BTreeSet<&str> =
metadata.requires_dist.iter().map(|d| d.trim()).collect();
if expected_deps != actual_deps {
bail!(
"{filename}'s Requires-Dist disagrees with the sdist: sdist deps={:?}, \
wheel deps={:?}",
expected_deps,
actual_deps,View on GitHub (pinned to 0267ce9170)
Solutions
- Rebuild all wheels from the pyproject currently passed via --pyproject-dir so Requires-Python matches the sdist.
- Pass --pyproject-dir at the pyproject that actually built these wheels, as the message suggests.
- Align requires-python in pyproject.toml across the wheel and sdist builds (e.g. after a version bump, rebuild everything).
Example fix
# before pyproject.toml (wheels): requires-python = ">=3.9" pyproject.toml (--pyproject-dir): requires-python = ">=3.8" # after set both to requires-python = ">=3.9" and rebuild the wheels
Defensive patterns
Strategy: validation
Validate before calling
# compare Requires-Python between wheel metadata and pyproject before publishing
diff <(unzip -p wheel/*.whl '*/METADATA' | grep '^Requires-Python:') \
<(grep '^requires-python' pyproject.toml) Try / catch
if let Err(e) = check_wheel_metadata_agrees(...) {
if e.to_string().contains("Requires-Python") {
eprintln!("rebuild wheels from the --pyproject-dir pyproject: {e:#}");
}
return Err(e);
} Prevention
- Rebuild all wheels whenever requires-python changes in pyproject.toml.
- Always pass the same pyproject directory that built the wheels via --pyproject-dir.
- Keep one canonical pyproject.toml; avoid stale copies in CI caches.
- Run the cross-check locally before publishing.
When it happens
Trigger: check_wheel_metadata_agrees (via build_release_sdist) compares metadata.requires_python against spec.requires_python and bails on any inequality, including one side being absent.
Common situations: Wheels built before a requires-python bump in pyproject.toml were cached and reused; --pyproject-dir points at the wrong project; one artifact set omits Requires-Python entirely.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- {filename}'s Requires-Dist disagrees with the sdist: sdist d
- no prebuilt {name} {ver} wheel for this platform; available
- {filename} has no *.dist-info/METADATA
- unsupported target triple {:?}
- this backend does not build sdists; use `dbt-ci pypi pack --
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/c206b52b69cffca1.
Report an issue: GitHub.