headroomlabs-ai/headroom · error · SystemExit

expected exactly one {pattern} in {out_dir}, found {len(matc

Error message

expected exactly one {pattern} in {out_dir}, found {len(matches)}

What it means

find_one_artifact() globs the output directory for a wheel or sdist pattern and requires exactly one match. Zero matches means the build produced nothing with the expected name; two or more means the pattern is ambiguous (typically several wheels from one maturin run, or leftovers from repeated builds).

Source

Thrown at scripts/build_python_release_smoke.py:90

        "build",
        "--out",
        out_dir,
        "--interpreter",
        python_exe,
    ]
    if release:
        build_args.append("--release")
    else:
        build_args.extend(["--profile", profile])
    run(build_args, env=env)

    run([python_exe, "-m", "maturin", "sdist", "--out", out_dir], env=env)


def find_one_artifact(out_dir: Path, pattern: str) -> Path:
    matches = sorted(out_dir.glob(pattern))
    if len(matches) != 1:
        raise SystemExit(f"expected exactly one {pattern} in {out_dir}, found {len(matches)}")
    return matches[0]


def verify_wheel(wheel: Path, expected_version: str) -> None:
    with zipfile.ZipFile(wheel) as archive:
        names = set(archive.namelist())
        native_members = [
            name
            for name in names
            if name.startswith("headroom/_core") and Path(name).suffix.lower() in {".pyd", ".so"}
        ]
        if not native_members:
            raise SystemExit(f"{wheel.name} does not contain headroom/_core native extension")

        metadata_members = [name for name in names if name.endswith(".dist-info/METADATA")]
        if len(metadata_members) != 1:
            raise SystemExit(
                f"{wheel.name} should contain exactly one dist-info/METADATA, "

View on GitHub (pinned to 322425c43b)

Solutions

  1. Inspect out_dir (`ls`) and reconcile what is there against the pattern passed to find_one_artifact.
  2. If duplicates exist, clear the directory and rerun so exactly one artifact per pattern is produced.
  3. If zero match, verify the version used in the pattern equals the version in the built artifact filenames (pyproject version vs expected_version).
  4. If maturin is invoked with multiple interpreters, restrict to one or tighten the pattern per tag.
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def expect_single_match(out_dir: Path, pattern: str) -> Path | None:
    matches = sorted(out_dir.glob(pattern))
    return matches[0] if len(matches) == 1 else None
# before the smoke step: assert expect_single_match(...) is not None,
# and if it is None, print sorted(p.name for p in out_dir.iterdir())

Prevention

When it happens

Trigger: Multiple wheels for different platforms/tags in out_dir; running maturin twice into the same directory; a version mismatch so the glob pattern (which includes the version) matches nothing; sdist and wheel both matching a too-loose pattern.

Common situations: Rebuilding after a version bump without clearing out_dir; maturin configured with multiple interpreters (`-i python3.11 -i python3.12`) producing one wheel per interpreter; abi3 wheel naming differing from the expected pattern.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/1a8b48381d2297fb. Report an issue: GitHub.