{"record":{"id":"ee21a1daca2b261a","repo":"apache/flink","slug":"error-ee21a1","errorCode":null,"errorMessage":"{}","messagePattern":"\\{\\}","errorType":"exception","errorClass":"KeyFieldOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/RowComparator.java","lineNumber":181,"sourceCode":"    public void getFlatComparator(List<TypeComparator> flatComparators) {\n        for (NullAwareComparator<Object> c : comparators) {\n            Collections.addAll(flatComparators, c.getFlatComparators());\n        }\n    }\n\n    @Override\n    public int hash(Row record) {\n        int code = 0;\n        int i = 0;\n\n        try {\n            for (; i < keyPositions.length; i++) {\n                code *= TupleComparatorBase.HASH_SALT[i & 0x1F];\n                Object element = record.getField(keyPositions[i]); // element can be null\n                code += comparators[i].hash(element);\n            }\n        } catch (IndexOutOfBoundsException e) {\n            throw new KeyFieldOutOfBoundsException(keyPositions[i]);\n        }\n\n        return code;\n    }\n\n    @Override\n    public void setReference(Row toCompare) {\n        int i = 0;\n        try {\n            for (; i < keyPositions.length; i++) {\n                TypeComparator<Object> comparator = comparators[i];\n                Object element = toCompare.getField(keyPositions[i]);\n                comparator.setReference(element); // element can be null\n            }\n        } catch (IndexOutOfBoundsException e) {\n            throw new KeyFieldOutOfBoundsException(keyPositions[i]);\n        }\n    }","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/RowComparator.java#L163-L199","documentation":"RowComparator.hash() iterates the configured key positions and calls record.getField(keyPositions[i]) on each. If a key position index is beyond the Row's arity (number of fields), Row.getField raises IndexOutOfBoundsException, which is caught and re-thrown as KeyFieldOutOfBoundsException with the message 'Field N is accessed for a key, but out of bounds in the record.' The comparator and the Row disagree on how many fields the Row has.","triggerScenarios":"The RowComparator is configured with keyPositions referencing field indices that the actual Row at runtime does not contain — e.g., comparator keys on position 3 but the Row only has 2 fields. This arises when the comparator's arity assumption diverges from the data's actual arity.","commonSituations":"The Row schema was changed (fields added or removed) without updating the key specification; a keyBy / sort uses positional indices computed against one schema but the upstream operator emits Rows with a different arity; a DataSet groupBy/sort with key positions [0,1,2] receives Rows of arity 2 due to a projection that was added without updating keys; legacy savepoint data with an older Row arity restored into a job whose comparator expects more fields.","solutions":["Align the key position indices with the actual Row arity — verify Row.getArity() matches the comparator's expected arity before the operation.","If you changed the Row schema, update the key specification (keyBy / sort / groupBy field indices) to reference valid positions.","Trace the upstream operator that produces the Row and confirm its output arity; add an arity check in a MapFunction if needed.","If restoring from a savepoint with a schema mismatch, implement a state migration or start from a clean savepoint."],"exampleFix":"// before — comparator keys on position 2 but Rows only have 2 fields (indices 0,1)\ndataSet.sortPartition(2, Order.ASCENDING); // Row arity = 2 → IOOBE\n\n// after — key on a valid position within the Row's arity\ndataSet.sortPartition(1, Order.ASCENDING); // valid: index 1 < arity 2","handlingStrategy":"validation","validationCode":"// Before hashing or keying a Row, validate all key positions are in bounds\npublic static void validateKeyPositions(Row row, int[] keyPositions) {\n    for (int pos : keyPositions) {\n        if (pos < 0 || pos >= row.getArity()) {\n            throw new IllegalArgumentException(\n                \"Key position \" + pos + \" is out of bounds for Row arity \" + row.getArity());\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    int hash = comparator.hash(record);\n} catch (KeyFieldOutOfBoundsException e) {\n    log.error(\"Row arity {} too small for key position {}\",\n        record.getArity(), e.getFieldNumber());\n    throw e;\n}","preventionTips":["Validate Row.getArity() >= (max(keyPositions)+1) before any keyed operation.","Keep key position arrays in sync with the Row schema — update both together.","Add a schema-validation MapFunction at the pipeline entry point.","Document expected Row arity alongside key specifications."],"tags":["row","comparator","key-position","arity-mismatch","dataset-api"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}