Skip to content
Latchkey

Java "Comparison method violates its general contract!" - Fix Sort in CI

A sort threw IllegalArgumentException: Comparison method violates its general contract!. Java’s TimSort detected that your Comparator/compareTo is not a valid total order - it is not antisymmetric, transitive, or consistent - and aborts rather than producing a wrong order.

What this error means

A Collections.sort/list.sort/Stream.sorted call fails with Comparison method violates its general contract!. It can appear only on larger inputs (TimSort only checks the contract past a threshold), which makes it look intermittent - but the comparator is genuinely broken.

stack trace
java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.base/java.util.TimSort.mergeHi(TimSort.java:903)
    at java.base/java.util.TimSort.mergeAt(TimSort.java:520)
    at java.base/java.util.Arrays.sort(Arrays.java:1307)
    at com.example.Ranker.rank(Ranker.java:48)

Common causes

Non-transitive or inconsistent comparator

A comparator that returns results inconsistent with itself - e.g. subtracting fields with overflow, comparing with == on doubles, or branching that breaks compare(a,b) == -compare(b,a) - violates the total-order contract.

Integer overflow in subtraction-based compare

Returning a.value - b.value overflows for large/negative values, flipping the sign and breaking antisymmetry. It often works for small data and fails once TimSort actually checks.

How to fix it

Build the comparator from safe primitives

Use Comparator.comparing* / Integer.compare so the order is total and overflow-free.

Java
// broken: overflow breaks antisymmetry
// list.sort((a, b) -> a.score - b.score);

// correct:
list.sort(Comparator.comparingInt(Item::score)
        .thenComparing(Item::name));

Ensure every field comparison is consistent

  1. Use Integer.compare/Double.compare, never raw subtraction.
  2. Make sure ties are broken consistently (chain thenComparing).
  3. Avoid comparisons that depend on mutable state changing during the sort.

How to prevent it

  • Construct comparators with Comparator.comparing* and Integer/Double.compare.
  • Never compare by subtraction (overflow) or by == on floating point.
  • Test sorting on large, adversarial datasets so contract violations surface in CI.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →