apache/flink · error · RuntimeException

Could not initialize basic comparator {}

Error message

Could not initialize basic comparator {}

What it means

BasicTypeInfo.instantiateComparator reflectively constructs the comparatorClass via comparatorClass.getConstructor(boolean.class).newInstance(ascending). If the comparator class lacks a public single-boolean constructor, or instantiation throws (security, missing constructor, abstract class), the failure is wrapped in a RuntimeException naming the comparator class. This is an internal contract violation: all basic comparators must have that constructor.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/typeinfo/BasicTypeInfo.java:309

    @PublicEvolving
    public static <X> BasicTypeInfo<X> getInfoFor(Class<X> type) {
        if (type == null) {
            throw new NullPointerException();
        }

        @SuppressWarnings("unchecked")
        BasicTypeInfo<X> info = (BasicTypeInfo<X>) TYPES.get(type);
        return info;
    }

    private static <X> TypeComparator<X> instantiateComparator(
            Class<? extends TypeComparator<X>> comparatorClass, boolean ascendingOrder) {
        try {
            Constructor<? extends TypeComparator<X>> constructor =
                    comparatorClass.getConstructor(boolean.class);
            return constructor.newInstance(ascendingOrder);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Could not initialize basic comparator " + comparatorClass.getName(), e);
        }
    }

    private static final Map<Class<?>, BasicTypeInfo<?>> TYPES =
            new HashMap<Class<?>, BasicTypeInfo<?>>();

    static {
        TYPES.put(String.class, STRING_TYPE_INFO);
        TYPES.put(Boolean.class, BOOLEAN_TYPE_INFO);
        TYPES.put(boolean.class, BOOLEAN_TYPE_INFO);
        TYPES.put(Byte.class, BYTE_TYPE_INFO);
        TYPES.put(byte.class, BYTE_TYPE_INFO);
        TYPES.put(Short.class, SHORT_TYPE_INFO);
        TYPES.put(short.class, SHORT_TYPE_INFO);
        TYPES.put(Integer.class, INT_TYPE_INFO);
        TYPES.put(int.class, INT_TYPE_INFO);
        TYPES.put(Long.class, LONG_TYPE_INFO);

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Ensure any custom comparator class passed to BasicTypeInfo has a public constructor accepting a single boolean (sort order).
  2. Prefer using the built-in basic types rather than registering a custom BasicTypeInfo with a bespoke comparator.
  3. If running on a restricted JDK, open the comparator package to reflective access or avoid custom comparators.

Example fix

// before
class MyComparator implements TypeComparator<X> {
    public MyComparator() {} // missing boolean arg -> throws
}

// after
class MyComparator implements TypeComparator<X> {
    public MyComparator(boolean ascending) { ... }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify the comparator class has the required constructor before relying on it
try {
    comparatorClass.getConstructor(boolean.class);
} catch (NoSuchMethodException e) {
    throw new IllegalStateException(
        comparatorClass + " must have a public (boolean) constructor", e);
}

Type guard

static boolean hasBooleanCtor(Class<? extends TypeComparator<?>> c) {
    try { c.getConstructor(boolean.class); return true; }
    catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
    return BasicTypeInfo.instantiateComparator(clazz, asc);
} catch (RuntimeException e) {
    throw new IllegalStateException(
        "Comparator " + clazz + " is misconfigured; check its constructor", e);
}

Prevention

When it happens

Trigger: A custom BasicTypeInfo registered with a comparatorClass that does not expose a public (boolean) constructor; reflective instantiation hitting an InstantiationException because the class is abstract or an interface; a security manager blocking reflective access.

Common situations: User-defined basic type info with a comparator that breaks the boolean-constructor contract; shaded or relocated comparator classes whose constructor signature changed; JVM module/access restrictions on reflective construction in newer JDKs.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/8d1b31eece585b38. Report an issue: GitHub.