{"record":{"id":"cc1008b39d7327eb","repo":"apache/flink","slug":"could-not-add-a-comparator-for-the-logicalkey-fiel","errorCode":null,"errorMessage":"Could not add a comparator for the logicalkey field index {}.","messagePattern":"Could not add a comparator for the logicalkey field index (.+?)\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/typeutils/CompositeType.java","lineNumber":179,"sourceCode":"                                            new int[] {logicalKeyField},\n                                            new boolean[] {orders[logicalKeyFieldIndex]},\n                                            logicalField,\n                                            config));\n\n                    comparatorAdded = true;\n                }\n\n                if (localFieldType instanceof CompositeType) {\n                    // we need to subtract 1 because we are not accounting for the local field (not\n                    // accessible for the user)\n                    logicalField += localFieldType.getTotalFields() - 1;\n                }\n\n                logicalField++;\n            }\n\n            if (!comparatorAdded) {\n                throw new IllegalArgumentException(\n                        \"Could not add a comparator for the logical\"\n                                + \"key field index \"\n                                + logicalKeyFieldIndex\n                                + \".\");\n            }\n        }\n\n        return builder.createTypeComparator(config);\n    }\n\n    // --------------------------------------------------------------------------------------------\n\n    @PublicEvolving\n    protected interface TypeComparatorBuilder<T> {\n        void initializeTypeComparatorBuilder(int size);\n\n        void addComparatorField(int fieldId, TypeComparator<?> comparator);\n","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/typeutils/CompositeType.java#L161-L197","documentation":"Thrown by CompositeType.createComparator when the loop over the type's fields completes without finding any field (atomic or composite) whose logical field range contains the requested logicalKeyFieldIndex. In other words the key position specified is out of the valid range of flat fields for this composite type, so no comparator could be attached.","triggerScenarios":"Calling keyBy or defining a sort/join key with a positional index that exceeds the total number of flat (flattened) fields in the CompositeType. For a Tuple2, valid flat positions are 0 and 1; requesting position 2 or higher throws. For POJOs with nested composite fields, the logical index must account for flattened sub-fields.","commonSituations":"Using a positional key selector (e.g. tuple -> position) with an index beyond arity. Specifying key positions on a Tuple after adding fields without updating the key index. Mixing positional field selectors with nested tuples where the logical offset arithmetic is miscounted. Passing a negative key field index.","solutions":["Ensure every value in the logicalKeyFields array is within [0, getTotalFields()-1] of the composite type.","Prefer field-name or lambda-based key selectors (KeySelector) over positional indices to avoid off-by-one errors.","For nested composite types, remember that getTotalFields() flattens nested fields — compute the valid range from getTotalFields(), not getArity().","Add a unit test that calls createComparator with your key positions against the inferred TypeInformation."],"exampleFix":"// before — key position out of bounds for Tuple2\nDataStream<Tuple2<String, Integer>> ds = ...;\nds.keyBy(2) // throws: only positions 0, 1 are valid\n\n// after — valid key position\nds.keyBy(0) // ok\n\n// or use a KeySelector to avoid positional mistakes\nds.keyBy(t -> t.f0)","handlingStrategy":"validation","validationCode":"// Validate key positions against the composite type's total flat field count\nCompositeType<?> composite = (CompositeType<?>) typeInfo;\nint totalFields = composite.getTotalFields();\nfor (int pos : keyPositions) {\n    if (pos < 0 || pos >= totalFields) {\n        throw new IllegalArgumentException(\n            \"Key position \" + pos + \" out of range [0, \" + (totalFields - 1) + \"]\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer field-name or KeySelector-based keys over positional indices.","When using positions, compute the valid range from getTotalFields() (not getArity()) for nested types.","Unit-test keyBy calls against the inferred TypeInformation."],"tags":["type-system","composite-type","comparator","key-selector","illegal-argument"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}