dbt-labs/dbt-core · error · anyhow
{filename} has no *.dist-info/METADATA
Error message
{filename} has no *.dist-info/METADATA What it means
check_wheel_metadata_agrees expects every candidate wheel to contain a *.dist-info/METADATA file inside its zip. If wheel_metadata returns None (no METADATA entry found), the function bails because Requires-Python and Requires-Dist cross-checks are impossible without it.
Source
Thrown at crates/dbt-ci/src/sdist.rs:145
}
build_sdist(spec, &version_pep440, &wheels, base_url, out_dir)
}
/// Fails the release when the sdist's static metadata disagrees with a wheel it
/// 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();View on GitHub (pinned to 0267ce9170)
Solutions
- Verify the file is a proper wheel (unzip -l FILE | grep 'dist-info/METADATA') and rebuild it with a real wheel builder if not.
- Ensure you are passing wheel files (.whl), not sdists or plain zips, as targets.
- Re-run the wheel build (maturin/cibuildwheel) if the wheel was truncated during upload/download (also check the recorded sha256).
Example fix
# before unzip -l dbt_core-1.0.0.zip # no dist-info/METADATA -> error # after maturin build --release # produce a real .whl and pass that path
Defensive patterns
Strategy: validation
Validate before calling
# verify each wheel contains METADATA before handing it to the pipeline
for whl in wheels/*.whl; do
unzip -l "$whl" | grep -q 'dist-info/METADATA' || { echo "$whl has no METADATA" >&2; exit 1; }
done Type guard
fn looks_like_wheel(path: &Path) -> bool {
path.extension().map_or(false, |e| e == "whl")
} Try / catch
match check_wheel_metadata_agrees(...) {
Err(e) if e.to_string().contains("no *.dist-info/METADATA") => {
eprintln!("not a valid wheel; rebuild it: {e:#}");
std::process::exit(1);
}
r => r,
} Prevention
- Only feed files produced by a real wheel builder (maturin/cibuildwheel) into the pipeline.
- Verify wheel integrity with sha256 after download/upload.
- Glob asset inputs narrowly (*.whl) so sdists/zips cannot slip in.
When it happens
Trigger: Passing a file to build_release_sdist / check_wheel_metadata_agrees that is not a valid wheel (no .dist-info/METADATA in the zip): a raw .tar.gz, a corrupted/truncated wheel, or a zip built without dist-info.
Common situations: Pointing --target/asset globs at artifacts that aren't wheels, a build step producing broken wheels, or manually renamed/zipped files being fed to the cross-check.
Related errors
- no prebuilt {name} {ver} wheel for this platform; available
- {filename} declares Requires-Python {actual:?} but the sdist
- {filename}'s Requires-Dist disagrees with the sdist: sdist d
- unsupported target triple {:?}
- {}: missing `[project].name`
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/13a23d32ff8b835e.
Report an issue: GitHub.