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
- Clean and rebuild: run mvn clean package in java/, then rebuild the wheel so exactly one jar remains.
- Manually remove stale jars from java/opendataloader-pdf-cli/target/ matching the glob, leaving only the current version.
- 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
- Use mvn clean package (not just mvn package) on version bumps so stale jars are removed.
- In CI, never reuse target/ across versions without cleaning.
- Glob and assert exactly one jar before invoking the wheel build.
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.