How is repository metadata matched to a dependency, and what happens when your library version has no matching metadata?
answer
- index.json maps group:artifact:version → metadata dir
- Version-scoped match, not 'any version'
- No match = nothing contributed, fails only native
- Upgrade can silently drop coverage
- Fix: pin/fork repo, downgrade, tracing agent, contribute
basics
~20 sMetadata is looked up by the dependency's group:artifact:version coordinates via the repository's index. If your exact version isn't covered, no metadata is contributed for that jar and you may hit reflection/resource failures unless you add your own hints.
solid answer
~40 sNative Build Tools reads each resolved dependency's `group:artifact:version` and looks it up in the repository's `index.json`, which maps coordinates to a per-library metadata directory and declares which versions each metadata set applies to. A match contributes that library's reflect/resource/proxy/serialization JSON into the native-image config. If your version isn't listed — common when a library releases faster than metadata is contributed — nothing is added for that jar, and reflective/resource-dependent code paths can fail only in the native image (the JVM still works). Mitigations: pin or point at a newer/forked repository version that covers it, downgrade to a covered version, run the GraalVM tracing agent to generate metadata and curate it into a `RuntimeHintsRegistrar`, or exclude and hand-write hints. Because matching is version-scoped, upgrading a dependency can silently drop coverage.
go deeper
Should know matching is by library coordinates.
Should know a missing version means no metadata and native-only failures.
Should anticipate upgrade-driven coverage drops and know the tracing-agent/fork mitigations.
Should mandate native integration tests in CI to catch coverage regressions before prod.
**Coordinate-based matching.** The repository is organized per library, and an `index.json` at the top maps Maven coordinates (`group:artifact`) to a directory, then per-version metadata. Native Build Tools takes your *resolved* dependency graph, and for each artifact's `group:artifact:version` consults the index to find a metadata set declared as applicable to that version. Matching is **coordinate + version scoped** — metadata files are associated with specific version ranges/lists, not 'any version'. **What a match contributes.** When found, the library's metadata JSON (`reflect-config.json`, `resource-config.json`, `proxy-config.json`, `serialization-config.json`, `jni-config.json` as applicable) is merged into the native-image arguments alongside your own Spring `RuntimeHints`. **No match.** If the exact version isn't covered: - **Nothing is contributed** for that jar — the build still succeeds. - Failures surface **only at native runtime** (missing class/method/resource), not on the JVM, which makes them easy to miss in JVM-based tests. This is the classic 'works on JVM, breaks native' trap. **Why gaps happen.** Libraries release faster than metadata is contributed; a plugin's *bundled* repository snapshot lags the latest metadata; a brand-new library has no entry yet. Crucially, **upgrading a dependency can drop coverage** if the metadata hasn't caught up to the new version — a silent regression. **Mitigations (in rough order).** 1. **Use a newer/pinned repository version** (`version`) or a **forked/local `uri`** that includes your version's metadata. 2. **Stay on a covered version** of the library until metadata lands. 3. **Generate metadata** with the GraalVM **tracing agent** (`-agentlib:native-image-agent=config-output-dir=...`) by exercising the app on the JVM, then curate the output into a `RuntimeHintsRegistrar` (don't dump raw agent output blindly). 4. **Contribute upstream** to `oracle/graalvm-reachability-metadata` so future builds are covered. 5. **Exclude** a wrong metadata set (Native Build Tools module filtering) and supply corrected hints. **Testing implication.** Run the GraalVM **native reachability/JUnit integration tests** (the plugin runs your tests inside a native image) so coverage gaps fail your build rather than production. Relying only on JVM tests hides these problems.
- Why can a dependency upgrade break a native build that previously worked?Matching is version-scoped. If the new version has no metadata entry yet, coverage is silently dropped and reflective paths can fail in the native image even though the JVM run is fine.
- How would you generate metadata for an uncovered library?Run the app on the JVM with the GraalVM tracing agent (native-image-agent) to record reflection/resource usage, then curate that output into a RuntimeHintsRegistrar or contribute it upstream — don't commit raw agent dumps blindly.
saying these in an interview costs you the question
- Assuming any version of a listed library is automatically covered
- Believing a missing match fails the build (it silently contributes nothing)
- Committing raw tracing-agent output as-is without curation