Troubleshooting
Common errors and how to fix them.
Checksum mismatch
error: checksum mismatch for com.example:foo:1.0.0
expected: a3f1b2c4...
actual: deadbeef...
The JAR on disk does not match the hash stored alongside it. This usually has one of three causes:
- Partial download — the download was interrupted and a truncated file was cached. Delete the artifact from
~/.m2/repositoryand re-runcurie build(orcurie fetch) to re-download it. - Corrupted local cache — the file was edited or truncated by another tool. Same fix: delete and re-fetch.
- Repository published a different artifact at the same version — rare, but happens with snapshot repositories. Verify the artifact hash from a trusted source; if the repository deliberately changed a released artifact, treat it as a security incident.
To delete a specific artifact:
rm -rf ~/.m2/repository/com/example/foo/1.0.0/
Missing artifact / artifact not found
error: artifact not found: com.example:foo:1.0.0
Curie could not find the artifact in any configured repository. Common causes:
- Version typo — double-check the version string in
Curie.toml. - Private repository not declared — if the artifact is in a private Nexus or Artifactory instance, add a
[[repositories]]entry pointing to it. See Resolver & checksums. - Artifact only exists in a snapshot repository — snapshot repositories must be explicitly listed; Curie does not add them by default.
- BOM version mismatch — if you declared an empty version
"", the BOM must include the artifact. Runcurie depsto see what version the BOM resolves to.
Offline build fails with cache miss
error: offline mode is enabled but artifact is not cached:
com.example:foo:1.0.0
You ran curie build --offline (or mvn --offline) but the artifact is not in ~/.m2/repository. The fix is to pre-fetch the missing artifact while online:
curie fetch com.example:foo:1.0.0
For a full offline setup — for example in a CI environment without internet access — use curie fetch --file to pre-populate the entire cache from a coordinate list. See the Bulk pre-fetch section for the workflow.
No main class found / multiple main classes
error: no main class found in compiled output error: multiple main classes found — set mainClass explicitly: com.example.App com.example.tools.DebugRunner
Curie scans compiled .class files for a public static void main(String[]) method (and for Java 21+ instance main methods). When it finds zero or more than one, the build fails.
- Zero found — make sure the main class is in a source directory Curie can see (
src/,src/main/java/, or flat-package layout). Check that it actually has a validmainsignature. - Multiple found — set
mainClass = "com.example.App"in the[application]section to pick one explicitly.
Build keeps recompiling even when nothing changed
Curie uses file modification timestamps and content hashes to detect changed inputs. If the build repeatedly recompiles despite no source changes, the most common causes are:
- Annotation processor generating non-deterministic output — some processors embed timestamps or random IDs in generated files. Each build produces different output, which triggers the next build to recompile. Check your processor's documentation for a stable-output mode.
- JDK version changed — Curie rebuilds when the running JDK version changes (detected automatically). If you are switching JDKs frequently (e.g. via
JAVA_HOME), this is expected behavior. PinreleaseVersionin[java]to suppress bytecode changes from JDK upgrades. - File system clock skew — rare in local development, more common in Docker volumes or NFS mounts. If timestamps are unreliable, Curie falls back to content hashing, which is slower but correct.
- Corrupted incremental state — delete
target/and run a clean build:curie buildafter removingtarget/.
Version range in dependency POM
error: version range "[4.9,)" is not supported — declare an explicit version
A transitive dependency POM declares a version range (e.g. [4.9,)) instead of a fixed version. Curie's resolver requires concrete versions for reproducibility. To fix it, add an explicit version for the affected artifact in [dependencies] (or [bom-imports]) so that Curie's nearest-wins rule selects your explicit version before the range-declaring transitive POM is reached:
[dependencies] # pin the version that the range "[4.9,)" would normally resolve to "junit:junit" = "4.13.2"
curie fetch resolves ranges for you. Unlike curie build (which always requires an explicit pin, for reproducibility), curie fetch is an ad-hoc download command. When it hits a range it queries maven-metadata.xml, computes the exact version Maven would select (the highest published version satisfying the range), and proposes a ready-to-run command:
error: non-deterministic version ranges in dependency graph
com.google.code.gson:gson
[2.9.1,2.11) → 2.10.1
Re-run with an explicit version for each ranged artifact:
curie fetch ch.epfl.scala:bsp4j:2.1.1 com.google.code.gson:gson:2.10.1
curie fetch accepts several coordinates at once; a supplied coordinate overrides the matching transitive range (it is pinned across every coordinate's graph). With curie fetch --file, the same fix is phrased as the coordinate line(s) to add to the file, so the file ends up listing the concrete versions you intend to use.
Workspace member builds in wrong order
error: could not resolve workspace dependency "core" — did you declare it in [workspace-dependencies]?
Curie computes a topological build order from [workspace-dependencies] entries. If a member depends on another member but doesn't declare the [workspace-dependencies] entry, Curie won't know to build the upstream member first.
Check that every intra-workspace dependency is declared:
[workspace-dependencies] core = { path = "../core" }
Missing checksum sidecar
error: no checksum sidecar found for com.example:foo:1.0.0
tried: .sha256, .sha1
Curie requires a .sha256 or .sha1 sidecar from the same repository as the artifact. If a repository is missing sidecars it usually means:
- The repository is a raw file server, not a proper Maven repository — Maven-compatible repositories always publish checksums.
- A corporate proxy is stripping sidecar files — contact your infrastructure team to allow
.sha256and.sha1through. - The artifact was uploaded manually without checksums — regenerate them with
mvn deploy:deploy-fileor your repository manager's REST API.
Still stuck?
Open an issue on GitHub. Include the full error output and the relevant section of your Curie.toml.