Interview replay
Full round replay — dependency conflicts
Timed verbal replay with pass/fail criteria per follow-up.
How to run this
The opener
“Two libraries need different versions of the same dependency. What happens?”
Budget: 45 seconds. Going long here is itself a fail signal.
Follow-ups
1. “Which version does Maven pick?”
Testing: The single most common misconception here.
Scoring
Pass: The one declared nearest the root, not the newest. A 3.4 at depth two beats a 3.12 at depth three — so a transitive dependency can downgrade a library, and adding an unrelated dependency later can change which path is nearest.
Fail: Says the newest, or says Maven and Gradle behave the same.
2. “And Gradle?”
Testing: Whether they know the tools differ.
Scoring
Pass: The highest version anyone asks for, regardless of depth. So the same dependency set can resolve to different jars under the two tools — which is worth knowing when a project migrates.
Fail: Assumes both use nearest-wins.
3. “What does the failure look like?”
Testing: Whether they name the right category.
Scoring
Pass: A linkage error from the JVM: NoSuchMethodError, NoSuchFieldError, AbstractMethodError, NoClassDefFoundError. Not an exception thrown by the library — the JVM refusing to link a call site whose exact signature is not on the classpath.
Fail: Says the build fails, or expects a ClassCastException.
4. “Why does NoSuchMethodError print a whole signature?”
Testing: Do they know what javac recorded?
Scoring
Pass: javac writes the resolved method descriptor into the call site, and the JVM later demands an exact match. That is why the message identifies the version you compiled against, and why the error means version mismatch rather than a typo.
Fail: Thinks it means the method was never written.
5. “The tests all passed. How did this reach production?”
Testing: Lazy linking — the reason this class of bug survives CI.
Scoring
Pass: Linking happens per call site, on first execution. The class loads fine and the common paths work; the error waits at the one call site nobody exercised — a refund, a month-end job, a retry branch.
Fail: Blames test coverage generally without naming lazy resolution.
6. “How would you find out where a version came from?”
Testing: Whether they have actually debugged one.
Scoring
Pass: mvn dependency:tree -Dverbose -Dincludes=<artifact>, which shows rejected versions and 'omitted for conflict with'. Gradle's dependencyInsight --dependency does the same. Then compare the signature in the error against what each version provides.
Fail: Says they would read the poms, or guess.
7. “How do you fix it?”
Testing: Pin, not patch.
Scoring
Pass: Pin one version deliberately in dependencyManagement or a Gradle constraint, choosing one that satisfies every caller, and prefer a BOM for anything shipped as a family. Then add dependencyConvergence to the enforcer so the next one fails the build.
Fail: Adds a direct dependency, or starts excluding things.
8. “Why not just add an exclusion?”
Testing: Whether they see what an exclusion asserts.
Scoring
Pass: An exclusion claims a path does not need that dependency, which is a claim about someone else's code. Used to silence a version conflict it removes a jar that was needed, turning a solvable version problem into a NoClassDefFoundError with no version to compare.
Fail: Treats exclusions as the normal fix.
9. “A static final int changed value in the upgrade and your code still sees the old one. Why?”
Testing: Constant inlining — the silent version of this bug.
Scoring
Pass: Compile-time constants are copied into every calling class, so there is no field read at runtime and nothing to relink. Modules you did not recompile keep the old value with no error at all, which is why a partial rebuild is not a valid test of an upgrade.
Fail: Says it should have picked up the new value.
10. “When is shading the right answer?”
Testing: Whether they weigh the cost.
Scoring
Pass: When publishing a library and unable to control consumers' classpaths. In an application, upgrading one of the two conflicting consumers is nearly always cheaper — the shaded copy is invisible to security scanning, stack traces get harder, and reflection by class name breaks.
Fail: Proposes shading as a general fix, or has not heard of it.
11. “How would you stop this happening again?”
Testing: Prevention rather than diagnosis.
Scoring
Pass: Fail the build on disagreement — enforcer's dependencyConvergence, or Gradle's failOnVersionConflict — plus a BOM for shared families and pins at the root where depth cannot move them. A lock file keeps CI and local resolving identically.
Fail: Says they would be more careful, or rely on tests.
Score yourself
← Back to Two libraries need different versions of the same dependency. What happens?