opendataloader-project/opendataloader-pdf · error · RuntimeError

Found multiple JAR files, expected one: {source_jar_paths}

Error message

Found multiple JAR files, expected one: {source_jar_paths}

What it means

RuntimeError raised by the hatch build hook when glob.glob matched MORE THAN ONE jar under java/opendataloader-pdf-cli/target/opendataloader-pdf-cli-*.jar. The hook expects exactly one (the current version) so it can copy it deterministically into the wheel; multiple matches usually mean stale jars from prior versions are sitting next to the new one.

Source

Thrown at python/opendataloader-pdf/hatch_build.py:51

        ):
            print("All required files already exist (building from sdist), skipping copy")
            return

        # --- Copy JAR ---
        print(f"Root DIR: {root_dir}")
        source_jar_glob = str(
            root_dir / "../../java/opendataloader-pdf-cli/target/opendataloader-pdf-cli-*.jar"
        )
        resolved_glob_path = Path(source_jar_glob).resolve()
        print(f"Searching for JAR file in: {resolved_glob_path}")

        source_jar_paths = glob.glob(source_jar_glob)
        if not source_jar_paths:
            raise RuntimeError(
                f"Could not find the JAR file. Please run 'mvn package' in the 'java/' directory first. Searched in: {resolved_glob_path}"
            )
        if len(source_jar_paths) > 1:
            raise RuntimeError(f"Found multiple JAR files, expected one: {source_jar_paths}")
        source_jar_path = source_jar_paths[0]
        print(f"Found source JAR: {source_jar_path}")

        dest_jar_dir.mkdir(parents=True, exist_ok=True)
        print(f"Copying JAR to {dest_jar_path}")
        shutil.copy(source_jar_path, dest_jar_path)

        # --- Copy LICENSE, NOTICE ---
        # README is copied by build-python.sh before this hook runs, because
        # hatchling validates [project.readme] during metadata parsing, which
        # happens before build hooks. Do not copy README here.
        shutil.copy(root_dir / "../../LICENSE", license_path)
        shutil.copy(root_dir / "../../NOTICE", notice_path)
        third_party_src = root_dir / "../../THIRD_PARTY"
        print(f"Copying THIRD_PARTY directory to {third_party_dest}")
        if third_party_dest.exists():
            shutil.rmtree(third_party_dest)
        shutil.copytree(third_party_src, third_party_dest)

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Clean and rebuild: run mvn clean package in java/, then rebuild the wheel so exactly one jar remains.
  2. Manually remove stale jars from java/opendataloader-pdf-cli/target/ matching the glob, leaving only the current version.
  3. Pin the build to mvn clean package in CI so target/ is always fresh before the wheel build.

Example fix

# before: stale jars accumulate
$ ls java/opendataloader-pdf-cli/target/*.jar
opendataloader-pdf-cli-1.0.0.jar  opendataloader-pdf-cli-1.1.0.jar
# after: clean rebuild yields a single jar
$ (cd java && mvn clean package)
$ ls java/opendataloader-pdf-cli/target/*.jar
opendataloader-pdf-cli-1.1.0.jar
Defensive patterns

Strategy: validation

Validate before calling

# Pre-build check enforcing exactly one jar:
import glob
jars = glob.glob("java/opendataloader-pdf-cli/target/opendataloader-pdf-cli-*.jar")
if len(jars) > 1:
    raise SystemExit(f"Multiple jars found {jars}; run: (cd java && mvn clean package)")

Type guard

def is_multiple_jar_error(exc: RuntimeError) -> bool:
    return isinstance(exc, RuntimeError) and "Found multiple JAR files" in str(exc)

Try / catch

# CI step: clean before package so target/ has exactly one jar.
#   (cd java && mvn clean package) && pip install .

Prevention

When it happens

Trigger: Running the Python build when target/ contains several versioned jars — e.g. opendataloader-pdf-cli-1.0.0.jar and opendataloader-pdf-cli-1.1.0.jar — because mvn clean was not run between version bumps or SNAPSHOT jars accumulated.

Common situations: Version bump without mvn clean leaves the old jar. Concurrent/parallel Maven runs in the same target. Release artifacts left from a prior release build. SNAPSHOT + release jars coexist.

Related errors


AI-assisted analysis of opendataloader-project/opendataloader-pdf@a7789b8e77 (2026-08-14). Data as JSON: /api/errors/59301c80cc2e1a6c. Report an issue: GitHub.