apache/flink · critical · RuntimeException

Unable to find key class.

Error message

Unable to find key class.

What it means

Thrown during Java deserialization of HadoopInputFormatBase when readObject() cannot load the key class by name via Class.forName(keyClassName, true, contextClassLoader). The key class name was serialized from the client; if the TaskManager classloader cannot resolve it, deserialization fails with this RuntimeException and the task cannot start.

Source

Thrown at flink-connectors/flink-hadoop-compatibility/src/main/java/org/apache/flink/api/java/hadoop/mapreduce/HadoopInputFormatBase.java:333

            this.mapreduceInputFormat =
                    (org.apache.hadoop.mapreduce.InputFormat<K, V>)
                            Class.forName(
                                            hadoopInputFormatClassName,
                                            true,
                                            Thread.currentThread().getContextClassLoader())
                                    .newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Unable to instantiate the hadoop input format", e);
        }
        try {
            this.keyClass =
                    (Class<K>)
                            Class.forName(
                                    keyClassName,
                                    true,
                                    Thread.currentThread().getContextClassLoader());
        } catch (Exception e) {
            throw new RuntimeException("Unable to find key class.", e);
        }
        try {
            this.valueClass =
                    (Class<V>)
                            Class.forName(
                                    valueClassName,
                                    true,
                                    Thread.currentThread().getContextClassLoader());
        } catch (Exception e) {
            throw new RuntimeException("Unable to find value class.", e);
        }
    }
}

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Include the key class (and all its transitive dependencies) in the user-code jar submitted with the job.
  2. If using shading, verify the key class's runtime name matches what was serialized (keep the class unshaded or remap consistently).
  3. Rebuild and resubmit the fat jar so the TaskManager classloader can resolve the key type.
  4. Confirm the key class is public and loadable by the user-code classloader.
Defensive patterns

Strategy: validation

Validate before calling

// Verify the key class is resolvable on the runtime classpath before submitting
String keyName = keyClass.getName();
try {
    Class.forName(keyName, true, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
    throw new IllegalStateException("Key class " + keyName
        + " is not on the runtime classpath; ship it in the user-code jar", e);
}

Prevention

When it happens

Trigger: Triggered on the TaskManager when Class.forName(keyClassName, true, contextClassLoader) fails during readObject() — e.g. the key class is not on the TaskManager classpath, was shaded/renamed, or the user jar shipping it was not attached to the job.

Common situations: Custom Writable key type lives in a jar not shipped to the cluster; key class relocated by a shading plugin so the runtime name differs from the serialized name; Avro/Protobuf-generated key class missing from the fat jar; mismatched dependency versions where the class package changed.

Related errors


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