apache/flink · error · RuntimeException

Could not create the type information for '{}'. The most com

Error message

Could not create the type information for '{}'. The most common reason is failure to infer the generic type information, due to Java's type erasure. In that case, please pass a 'TypeHint' instead of a class to describe the type. For example, to describe 'Tuple2<String, String>' as a generic type, use 'new PravegaDeserializationSchema<>(new TypeHint<Tuple2<String, String>>(){}, serializer);'

What it means

Thrown by the v1 StateDescriptor constructor when TypeExtractor.createTypeInfo(Class) fails to build TypeInformation for the passed class. Because Java erases generic type parameters at runtime, passing a raw Class like MyPojo.class or Tuple2.class gives the extractor nothing to recover the generics from. The message itself directs you to use a TypeHint to capture the full parameterized type at compile time.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/state/StateDescriptor.java:165

    /**
     * Create a new {@code StateDescriptor} with the given name and the given type information.
     *
     * <p>If this constructor fails (because it is not possible to describe the type via a class),
     * consider using the {@link #StateDescriptor(String, TypeInformation, Object)} constructor.
     *
     * @param name The name of the {@code StateDescriptor}.
     * @param type The class of the type of values in the state.
     * @param defaultValue The default value that will be set when requesting state without setting
     *     a value before.
     */
    protected StateDescriptor(String name, Class<T> type, @Nullable T defaultValue) {
        this.name = checkNotNull(name, "name must not be null");
        checkNotNull(type, "type class must not be null");

        try {
            this.typeInfo = TypeExtractor.createTypeInfo(type);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Could not create the type information for '"
                            + type.getName()
                            + "'. "
                            + "The most common reason is failure to infer the generic type information, due to Java's type erasure. "
                            + "In that case, please pass a 'TypeHint' instead of a class to describe the type. "
                            + "For example, to describe 'Tuple2<String, String>' as a generic type, use "
                            + "'new PravegaDeserializationSchema<>(new TypeHint<Tuple2<String, String>>(){}, serializer);'",
                    e);
        }

        this.defaultValue = defaultValue;
    }

    // ------------------------------------------------------------------------

    /** Returns the name of this {@code StateDescriptor}. */
    public String getName() {
        return name;

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Switch to the TypeInformation-based constructor: new ValueStateDescriptor<>("name", TypeInformation.of(new TypeHint<Tuple2<String,String>>(){}), defaultValue).
  2. If the value type is non-generic and POJO-compliant, ensure the class is public, top-level or static-nested, and has a public no-arg constructor before keeping the Class-based constructor.
  3. Pass a pre-built TypeInformation directly if you already compute it elsewhere, avoiding the Class path entirely.
  4. Catch and reconfigure at job-assembly time (the error surfaces at graph construction, before submission) so the job never submits with an unresolvable type.

Example fix

// before
new ValueStateDescriptor<>("events", Tuple2.class, defaultValue);

// after
new ValueStateDescriptor<>(
    "events",
    TypeInformation.of(new TypeHint<Tuple2<String,String>>(){}),
    defaultValue);
Defensive patterns

Strategy: validation

Validate before calling

// Before constructing a Class-based StateDescriptor, verify the type is non-generic
Class<?> type = MyValue.class;
if (type.getTypeParameters().length > 0) {
    throw new IllegalArgumentException(
        "Use a TypeHint/TypeInformation-based constructor for generic type " + type.getName());
}
// or build TypeInformation up front and catch InvalidTypesException
TypeInformation<?> ti;
try {
    ti = TypeExtractor.createTypeInfo(type);
} catch (InvalidTypesException e) {
    // fall back to TypeHint at a concrete call site
    ti = TypeInformation.of(new TypeHint<MyGeneric<String>>(){});
}

Type guard

// Guard: only use the Class-based ctor when the class has no type parameters
static boolean isSafeForClassCtor(Class<?> c) {
    return c.getTypeParameters().length == 0;
}

Try / catch

// Not recommended to catch at runtime; fix at construction time by switching to TypeInformation/TypeHint ctor.
// If wrapping generic builder code:
try {
    descriptor = new ValueStateDescriptor<>(name, clazz, defaultValue);
} catch (RuntimeException e) {
    throw new IllegalArgumentException(
        "Could not build TypeInformation for " + clazz.getName()
        + ". Provide a TypeHint-based descriptor.", e);
}

Prevention

When it happens

Trigger: Constructing a StateDescriptor subclass (ValueStateDescriptor, ListStateDescriptor, etc.) via the (String name, Class<T> type, T defaultValue) overload where T is itself a generic type whose parameters are erased, or where TypeExtractor cannot introspect the class (non-public class, missing no-arg constructor, unresolvable type variables in supertype). Also fires if createTypeInfo throws any Exception for non-generic reasons (malformed POJO).

Common situations: Defining state for Tuple2<String,String> or List<Event> using the Class-based constructor; passing an inner (non-static) class as the state value type; migrating a job whose state value class had generics and switching to the Class-based constructor by mistake.

Related errors


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