apache/flink · error · RuntimeException

Failed to serialize row.

Error message

Failed to serialize row.

What it means

AvroRowDataSerializationSchema.serialize wraps any exception from the RowData->GenericRecord conversion or the nested Avro encoder in a RuntimeException('Failed to serialize row.'). It almost always means a field value in the RowData does not fit the declared row type / Avro schema (null in a non-nullable field, wrong physical type, unsupported logical type).

Source

Thrown at flink-formats/flink-avro/src/main/java/org/apache/flink/formats/avro/AvroRowDataSerializationSchema.java:122

    @Override
    public void open(InitializationContext context) throws Exception {
        this.nestedSchema.open(context);
        if (this.nestedSchema instanceof AvroSerializationSchema) {
            this.schema = ((AvroSerializationSchema<GenericRecord>) this.nestedSchema).getSchema();
        } else {
            this.schema = AvroSchemaConverter.convertToSchema(rowType);
        }
    }

    @Override
    public byte[] serialize(RowData row) {
        try {
            // convert to record
            final GenericRecord record = (GenericRecord) runtimeConverter.convert(schema, row);
            return nestedSchema.serialize(record);
        } catch (Exception e) {
            throw new RuntimeException("Failed to serialize row.", e);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        AvroRowDataSerializationSchema that = (AvroRowDataSerializationSchema) o;
        return nestedSchema.equals(that.nestedSchema) && rowType.equals(that.rowType);
    }

    @Override
    public int hashCode() {
        return Objects.hash(nestedSchema, rowType);

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Log the failing RowData (the cause carries the per-field message 'Fail to serialize at field: %s' when it comes from the row converter) and fix that field's value or type.
  2. Make the corresponding Avro schema field nullable (union with null) if nulls are legitimate, or filter/replace nulls before serialization.
  3. Align the RowType used to construct the schema with the actual RowData produced upstream (no silent type mismatches).

Example fix

// before
// DDL: name STRING (non-nullable in Avro), but rows contain null

// after
// DDL: name STRING, or make the Avro field nullable:
// {"name":"name","type":["null","string"],"default":null}
Defensive patterns

Strategy: validation

Validate before calling

for (int i = 0; i < rowType.getFieldCount(); i++) {
    LogicalType ft = rowType.getTypeAt(i);
    if (!ft.isNullable() && row.isNullAt(i)) {
        throw new IllegalArgumentException("Null in non-nullable field: " + rowType.getFieldNames().get(i));
    }
}

Try / catch

try {
    out.collect(serializer.serialize(row));
} catch (RuntimeException e) { // 'Failed to serialize row.'
    if (e.getCause() != null && e.getCause().getMessage() != null
            && e.getCause().getMessage().startsWith("Fail to serialize at field:")) {
        // field-level cause available; route record to DLQ
        ctx.output(dlqTag, row);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A null value in a field whose Avro schema is not a nullable union; a RowData field carrying a different physical type than the LogicalType the converters were built from; a TIMESTAMP_WITH_LOCAL_TIME_ZONE column when legacy timestamp mapping is on (propagates from RowDataToAvroConverters).

Common situations: Upstream operator changed nullability or types after the format was built; SQL DDL column types drifted from the actual Avro schema; mixed Flink versions where timestamp mapping defaults changed.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/22d288c039144e2d. Report an issue: GitHub.