{"record":{"id":"d5d3b044621f3dd9","repo":"apache/flink","slug":"the-partitioner-is-incompatible-with-the-key-type","errorCode":null,"errorMessage":"The partitioner is incompatible with the key type. Partitioner type: {typeInfo} , key type: {keyType}","messagePattern":"The partitioner is incompatible with the key type\\. Partitioner type: (.+?) , key type: (.+?)","errorType":"exception","errorClass":"InvalidProgramException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/operators/Keys.java","lineNumber":186,"sourceCode":"            if (keyFields.size() != 1) {\n                throw new InvalidProgramException(\n                        \"Custom partitioners can only be used with keys that have one key field.\");\n            }\n\n            if (typeInfo == null) {\n                // try to extract key type from partitioner\n                try {\n                    typeInfo = TypeExtractor.getPartitionerTypes(partitioner);\n                } catch (Throwable t) {\n                    // best effort check, so we ignore exceptions\n                }\n            }\n\n            // only check if type is known and not a generic type\n            if (typeInfo != null && !(typeInfo instanceof GenericTypeInfo)) {\n                // check equality of key and partitioner type\n                if (!keyType.equals(typeInfo)) {\n                    throw new InvalidProgramException(\n                            \"The partitioner is incompatible with the key type. \"\n                                    + \"Partitioner type: \"\n                                    + typeInfo\n                                    + \" , key type: \"\n                                    + keyType);\n                }\n            }\n        }\n\n        @Override\n        public String toString() {\n            return \"Key function (Type: \" + keyType + \")\";\n        }\n    }\n\n    /** Represents (nested) field access through string and integer-based keys */\n    public static class ExpressionKeys<T> extends Keys<T> {\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/operators/Keys.java#L168-L204","documentation":"Thrown by SelectorFunctionKeys.validateCustomPartitioner() when the custom Partitioner's type argument differs from the key type. The partitioner receives the key value, so Partitioner<E> must be parameterised by the same E as the key (e.g. Partitioner<String> for a String key); a mismatch would cause ClassCastException at runtime.","triggerScenarios":"Calling partitionCustom(new MyIntPartitioner(), stringKeySelector) where the partitioner implements Partitioner<Integer> but the key is a String; attaching a Partitioner<Long> to a key whose TypeInformation is BasicTypeInfo.INT_TYPE_INFO.","commonSituations":"Reusing a partitioner written for one key type against a different key; type-erasure hiding the mismatch until validation; refactoring a key type (e.g. Long to String) without updating the partitioner.","solutions":["Implement Partitioner<E> with E exactly matching the key's TypeInformation.","If the key type changed, write a new partitioner for the new type.","For GenericTypeInfo keys the check is skipped (best-effort), but prefer a concrete key type so the mismatch is caught early."],"exampleFix":"// before (key is String, partitioner is Partitioner<Integer>)\nPartitioner<Integer> p = new MyIntPartitioner();\nds.partitionCustom(p, stringSel);\n// after\nds.partitionCustom(new MyStringPartitioner(), stringSel);","handlingStrategy":"validation","validationCode":"TypeInformation<?> partitionerType = TypeExtractor.getPartitionerTypes(partitioner);\nif (partitionerType != null && !partitionerType.equals(keyType)) {\n    throw new IllegalArgumentException(\n        \"Partitioner \" + partitionerType + \" incompatible with key \" + keyType);\n}","typeGuard":"static <E> boolean partitionerMatchesType(Partitioner<E> p, TypeInformation<E> keyType) {\n    try {\n        TypeInformation<?> pt = TypeExtractor.getPartitionerTypes(p);\n        return pt == null || pt.equals(keyType);\n    } catch (Throwable t) { return true; }\n}","tryCatchPattern":null,"preventionTips":["Implement Partitioner<E> with E exactly equal to the key TypeInformation.","When the key type changes, write a new partitioner rather than reusing the old one.","Prefer concrete (non-generic) key types so the mismatch is caught at validation, not runtime."],"tags":["flink-core","keys","custom-partitioner","type-compatibility","validation"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}