{"record":{"id":"0d10735a34e6389d","repo":"apache/flink","slug":"the-implementation-of-abstractdeserializationschem","errorCode":null,"errorMessage":"The implementation of AbstractDeserializationSchema is using a generic variable. This is not supported, because due to Java's generic type erasure, it will not be possible to determine the full type at runtime. For generic implementations, please pass the TypeInformation or type class explicitly to the constructor.","messagePattern":"The implementation of AbstractDeserializationSchema is using a generic variable\\. This is not supported, because due to Java's generic type erasure, it will not be possible to determine the full type at runtime\\. For generic implementations, please pass the TypeInformation or type class explicitly to the constructor\\.","errorType":"exception","errorClass":"FlinkRuntimeException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/serialization/AbstractDeserializationSchema.java","lineNumber":107,"sourceCode":"     * <p>This constructor is usable whenever the DeserializationSchema concretely defines its type,\n     * without generic variables:\n     *\n     * <pre>{@code\n     * public class MyDeserializationSchema extends AbstractDeserializationSchema<MyType> {\n     *\n     *     public MyType deserialize(byte[] message) throws IOException {\n     *         ...\n     *     }\n     * }\n     * }</pre>\n     */\n    protected AbstractDeserializationSchema() {\n        try {\n            this.type =\n                    TypeExtractor.createTypeInfo(\n                            AbstractDeserializationSchema.class, getClass(), 0, null, null);\n        } catch (InvalidTypesException e) {\n            throw new FlinkRuntimeException(\n                    \"The implementation of AbstractDeserializationSchema is using a generic variable. \"\n                            + \"This is not supported, because due to Java's generic type erasure, it will not be possible to \"\n                            + \"determine the full type at runtime. For generic implementations, please pass the TypeInformation \"\n                            + \"or type class explicitly to the constructor.\",\n                    e);\n        }\n    }\n\n    /**\n     * Creates an AbstractDeserializationSchema that returns the TypeInformation indicated by the\n     * given class. This constructor is only necessary when creating a generic implementation, see\n     * {@link AbstractDeserializationSchema Generic Use}.\n     *\n     * <p>This constructor may fail if the class is generic. In that case, please use the\n     * constructor that accepts a {@link #AbstractDeserializationSchema(TypeHint) TypeHint}, or a\n     * {@link #AbstractDeserializationSchema(TypeInformation) TypeInformation}.\n     *\n     * @param type The class of the produced type.","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/serialization/AbstractDeserializationSchema.java#L89-L125","documentation":"Thrown by the no-arg constructor of AbstractDeserializationSchema when TypeExtractor cannot resolve the concrete type parameter at runtime due to Java generic type erasure. The schema must know its produced TypeInformation to build serializers; an unbound generic variable (e.g. <T>) makes that impossible. The fix is to supply the type explicitly via the alternate constructor that accepts a Class or TypeInformation.","triggerScenarios":"A subclass declares a generic type parameter (e.g. class MySchema<T> extends AbstractDeserializationSchema<T>) and relies on the implicit no-arg constructor instead of calling super(typeClass) or super(typeInfo). The TypeExtractor.createTypeInfo call throws InvalidTypesException, which the constructor wraps in this FlinkRuntimeException.","commonSituations":"Writing a reusable/generic deserialization schema library that is parameterized over a type T; refactoring a concrete schema to be generic without updating the constructor call; reusing a schema class across different POJO types.","solutions":["If the class is concrete, bind the type parameter directly: class MySchema extends AbstractDeserializationSchema<MyType> and keep the no-arg constructor.","If the class must be generic, accept the type in the constructor and forward it: public MySchema(Class<T> type) { super(type); } or public MySchema(TypeInformation<T> typeInfo) { super(typeInfo); }.","If you cannot change the class hierarchy, create a separate non-generic subclass per concrete type."],"exampleFix":"// before\npublic class MyGenericSchema<T> extends AbstractDeserializationSchema<T> {\n    public MyGenericSchema(Class<T> type) {\n        super(); // throws at runtime: T is erased\n    }\n    public T deserialize(byte[] message) { ... }\n}\n\n// after\npublic class MyGenericSchema<T> extends AbstractDeserializationSchema<T> {\n    public MyGenericSchema(Class<T> type) {\n        super(type); // passes type explicitly\n    }\n    public T deserialize(byte[] message) { ... }\n}","handlingStrategy":"validation","validationCode":"// Validate before instantiation that the type is concretely bound\nClass<?> typeClass = /* resolved at runtime */;\nif (typeClass == null) {\n    throw new IllegalArgumentException(\n        \"Cannot construct generic schema without an explicit type.\");\n}\n// Then use the explicit constructor\nAbstractDeserializationSchema<MyType> schema = new MySchema(typeClass);","typeGuard":"// Narrow: if the schema declares a generic T, require the Class/TypeInformation ctor\npublic static <T> boolean isSafelyConstructible(Class<? extends AbstractDeserializationSchema<T>> clazz) {\n    try {\n        return java.util.Arrays.stream(clazz.getConstructors())\n            .anyMatch(c -> c.getParameterCount() == 1\n                && (c.getParameterTypes()[0] == Class.class\n                    || c.getParameterTypes()[0] == TypeInformation.class));\n    } catch (Exception e) {\n        return false;\n    }\n}","tryCatchPattern":"// Not recommended — fix the constructor instead. But if catching:\ntry {\n    schema = new MyGenericSchema<>();\n} catch (FlinkRuntimeException e) {\n    if (e.getMessage().contains(\"generic variable\")) {\n        // re-construct with explicit type\n        schema = new MyGenericSchema<>(MyType.class);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always pass a Class or TypeInformation to AbstractDeserializationSchema subclasses that use a generic type parameter.","Add a unit test that instantiates the schema and calls getProducedType() to verify the type is resolved.","Avoid parameterizing the schema over <T> unless the type is supplied explicitly at construction."],"tags":["serialization","generics","type-erasure","type-information"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}