apache/flink · error · InvalidTypesException

The given class is no subclass of {}

Error message

The given class is no subclass of {}

What it means

Thrown by ValueTypeInfo.getValueTypeInfo when the provided class is not a valid subclass of org.apache.flink.types.Value — either it does not extend Value at all, or it is the raw Value.class interface itself (which has no concrete serialization behavior).

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/ValueTypeInfo.java:273

    @Override
    public boolean canEqual(Object obj) {
        return obj instanceof ValueTypeInfo;
    }

    @Override
    public String toString() {
        return "ValueType<" + type.getSimpleName() + ">";
    }

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

    @PublicEvolving
    static <X extends Value> TypeInformation<X> getValueTypeInfo(Class<X> typeClass) {
        if (Value.class.isAssignableFrom(typeClass) && !typeClass.equals(Value.class)) {
            return new ValueTypeInfo<X>(typeClass);
        } else {
            throw new InvalidTypesException(
                    "The given class is no subclass of " + Value.class.getName());
        }
    }
}

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Use a concrete Value subclass (e.g., IntValue, StringValue, or a custom class implementing Value) instead of Value.class itself.
  2. If the type is not a Value, use the appropriate TypeInformation (e.g., BasicTypeInfo for primitives, PojoTypeInfo for POJOs).
  3. Ensure generic code that constructs ValueTypeInfo resolves to a concrete Value subclass, not the raw Value interface.
  4. Register a custom TypeInfoFactory via @TypeInfo if you need custom type info for non-Value types.

Example fix

// before
TypeInformation<?> info = ValueTypeInfo.getValueTypeInfo(Value.class);
// throws: Value.class is not a valid subclass of itself

// after
TypeInformation<?> info = ValueTypeInfo.getValueTypeInfo(MyCustomValue.class);
// where MyCustomValue extends Value implements Value { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Check if the class is a valid concrete Value subclass
if (!Value.class.isAssignableFrom(typeClass) || typeClass.equals(Value.class)) {
    // not a valid Value subclass; use appropriate TypeInformation
}

Type guard

static boolean isValidValueSubclass(Class<?> typeClass) {
    return Value.class.isAssignableFrom(typeClass) && !typeClass.equals(Value.class);
}

Try / catch

try {
    TypeInformation<?> ti = ValueTypeInfo.getValueTypeInfo(typeClass);
} catch (InvalidTypesException e) {
    // use a concrete Value subclass or appropriate TypeInformation
    ti = TypeInformation.of(typeClass);
}

Prevention

When it happens

Trigger: Called when ValueTypeInfo.getValueTypeInfo(typeClass) is invoked with a class that is either not assignable to Value, or is exactly Value.class. This is used internally during type extraction to validate that a class is a concrete Value implementation before constructing a ValueTypeInfo.

Common situations: Passing a raw class that doesn't implement Value to a type extraction context expecting a Value type. Accidentally using Value.class as a type parameter instead of a concrete subclass like IntValue.class. Generic code that resolves the type parameter to Value.class itself rather than a concrete subclass.

Related errors


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