bazelbuild/bazel · error · ClassCastException

unsupported comparison: %s <=> %s

Error message

unsupported comparison: %s <=> %s

What it means

The underlying throw inside Starlark.compareUnchecked: after same-type comparison and the int/float special cases, the values are mutually unordered, so it raises ClassCastException('unsupported comparison: T1 <=> T2'). Higher-level callers translate this: EvalUtils.compare wraps it into EvalException (error 100) and MethodLibrary's min/max rethrow its getMessage() (error 101). You only see the raw ClassCastException if you call compareUnchecked or an ordering built on it directly from Java.

Source

Thrown at src/main/java/net/starlark/java/eval/Starlark.java:616

                  Starlark.reprForErrors(x), Starlark.reprForErrors(y)));
        }
      }

    } else {
      // different types

      if (x instanceof StarlarkFloat && y instanceof StarlarkInt) {
        // float < int
        double xf = ((StarlarkFloat) x).toDouble();
        return Double.isNaN(xf) ? +1 : -StarlarkInt.compareIntAndDouble((StarlarkInt) y, xf);
      } else if (x instanceof StarlarkInt && y instanceof StarlarkFloat) {
        // int < float
        double yf = ((StarlarkFloat) y).toDouble();
        return Double.isNaN(yf) ? -1 : StarlarkInt.compareIntAndDouble((StarlarkInt) x, yf);
      }
    }

    throw new ClassCastException(
        String.format("unsupported comparison: %s <=> %s", Starlark.type(x), Starlark.type(y)));
  }

  /**
   * Returns true if the given values are equal. Safe to use for potentially self-referential
   * Starlark data structures.
   *
   * @throws EvalException if x and/or y is a self-referential data structures (signaled by {@link
   *     Object#equals} overflowing the stack)
   */
  public static boolean checkedEquals(@Nullable Object x, @Nullable Object y) throws EvalException {
    if (x == null) {
      return y == null;
    }
    try {
      return x.equals(y);
    } catch (StackOverflowError unused) {
      throw Starlark.errorf(

View on GitHub (pinned to e6e199d060)

Solutions

  1. In host code, call the guarded wrapper (EvalUtils.compare semantics) or catch ClassCastException and translate it to your error type.
  2. Sort with an explicit key/ordering restricted to one type.
  3. Validate/normalize types before comparing (see error 100 fixes).

Example fix

// before
int cmp = Starlark.compareUnchecked(x, y); // raw ClassCastException on mismatch

// after
int cmp;
try {
  cmp = Starlark.compareUnchecked(x, y);
} catch (ClassCastException e) {
  throw new IllegalArgumentException("cannot order " + Starlark.type(x), e);
}
Defensive patterns

Strategy: try-catch

Try / catch

// Java host code calling compareUnchecked directly
try {
  int cmp = Starlark.compareUnchecked(x, y);
} catch (ClassCastException e) {
  throw new IllegalArgumentException("unsupported comparison: " + Starlark.type(x) + " <=> " + Starlark.type(y), e);
}

Prevention

When it happens

Trigger: Calling Starlark.compareUnchecked from Java embedding code (e.g. custom StarlarkCallable implementations or orderings) with e.g. a String and an Integer; using Guava Ordering.arbitrary()/natural() on mixed Starlark values outside MethodLibrary's guarded path.

Common situations: Embedding the Starlark interpreter in a host application and reusing compareUnchecked for sorting; custom builtins that sort their arguments without catching ClassCastException.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/7d6646eb387c6cbe. Report an issue: GitHub.