{"record":{"id":"a19c299292f729d3","repo":"apache/flink","slug":"row-arity-of-reuse-does-not-match-this-serial","errorCode":null,"errorMessage":"Row arity of reuse ({}) does not match this serializer's field length ({}).","messagePattern":"Row arity of reuse \\((.+?)\\) does not match this serializer's field length \\((.+?)\\)\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/RowSerializer.java","lineNumber":358,"sourceCode":"        for (int fieldPos = 0; fieldPos < length; fieldPos++) {\n            if (!mask[rowKindOffset + fieldPos]) {\n                fieldByPosition[fieldPos] = fieldSerializers[fieldPos].deserialize(source);\n            }\n        }\n\n        return RowUtils.createRowWithNamedPositions(kind, fieldByPosition, positionByName);\n    }\n\n    @Override\n    public Row deserialize(Row reuse, DataInputView source) throws IOException {\n        // reuse uses name-based field mode, do a non-reuse deserialize\n        if (reuse == null || reuse.getFieldNames(false) != null) {\n            return deserialize(source);\n        }\n        final int length = fieldSerializers.length;\n\n        if (reuse.getArity() != length) {\n            throw new RuntimeException(\n                    \"Row arity of reuse (\"\n                            + reuse.getArity()\n                            + \") does not match \"\n                            + \"this serializer's field length (\"\n                            + length\n                            + \").\");\n        }\n\n        // read bitmask\n        readIntoMask(source, mask);\n        if (supportsRowKind) {\n            reuse.setKind(readKindFromMask(mask));\n        }\n\n        // deserialize fields\n        for (int fieldPos = 0; fieldPos < length; fieldPos++) {\n            if (mask[rowKindOffset + fieldPos]) {\n                reuse.setField(fieldPos, null);","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/RowSerializer.java#L340-L376","documentation":"RowSerializer.deserialize(Row reuse, DataInputView) reads a Row from a DataInputView into the provided reuse Row (position-based path). It asserts reuse.getArity() == fieldSerializers.length before reading the null bitmask and field data. If the reuse Row has the wrong arity, this RuntimeException is thrown with both values. The binary format's bitmask is sized to the serializer's field count, so a mismatched reuse Row would corrupt deserialization.","triggerScenarios":"RowSerializer.deserialize(Row reuse, DataInputView) is called (e.g., during network read, state restore, or shuffle receive) with a reuse Row whose arity does not equal the serializer's field count.","commonSituations":"The reuse Row was pre-allocated for a different schema (different number of fields); a Row reuse pool sized for an old arity is still in use after a schema change; state restore from a savepoint where the reuse buffer was created for a previous Row schema; an operator reuses a Row object from a different source with a different arity.","solutions":["Allocate the reuse Row with exactly fieldSerializers.length fields: new Row(serializer.getArity()).","Do not reuse Row objects across serializers with different arities.","After a schema change, discard old reuse Row buffers and reallocate to the new arity.","Use RowSerializer.createInstance() to obtain a correctly-sized reuse Row."],"exampleFix":"// before — reuse Row arity mismatch\nRowSerializer ser = new RowSerializer(new TypeSerializer[]{intSer, strSer}); // arity 2\nRow reuse = new Row(3); // wrong\nser.deserialize(reuse, input); // arity 3 ≠ 2 → exception\n\n// after — reuse Row matches serializer arity\nRow reuse = ser.createInstance(); // arity 2, correctly sized\nser.deserialize(reuse, input); // OK","handlingStrategy":"validation","validationCode":"// Validate reuse arity before deserialize\npublic static Row safeDeserialize(RowSerializer ser, Row reuse, DataInputView in)\n        throws IOException {\n    if (reuse.getArity() != ser.getArity()) {\n        throw new IllegalArgumentException(\n            \"Reuse Row arity \" + reuse.getArity()\n            + \" != serializer arity \" + ser.getArity());\n    }\n    return ser.deserialize(reuse, in);\n}","typeGuard":null,"tryCatchPattern":"try {\n    Row result = serializer.deserialize(reuse, input);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"Row arity of reuse\")) {\n        log.error(\"Reuse arity {} != expected {}; reallocating\",\n            reuse.getArity(), serializer.getArity());\n        reuse = serializer.createInstance();\n        result = serializer.deserialize(reuse, input);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Obtain reuse Rows from serializer.createInstance() to guarantee correct arity.","Do not reuse Row buffers across different serializers.","Reallocate reuse buffers after schema changes.","Validate reuse arity before deserialize."],"tags":["row","serializer","arity-mismatch","deserialization","reuse"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}