alibaba/canal · error · CanalParseException

parse row data failed.

Error message

parse row data failed.

What it means

Thrown from the catch(Exception) block of parseRowsEvent() — it is the generic catch-all wrapping any non-CanalParse exception that occurs during row data parsing. The original exception is attached as the cause. This covers charset decoding failures, RowsLogBuffer underflows, NumberFormatException on numeric columns, and other unexpected data-level errors.

Source

Thrown at parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/dbsync/LogEventConvert.java:599

            }
            TableMapLogEvent table = event.getTable();
            Header header = createHeader(event.getHeader(),
                table.getDbName(),
                table.getTableName(),
                eventType,
                rowsCount);

            RowChange rowChange = rowChangeBuider.build();
            if (tableError) {
                Entry entry = createEntry(header, EntryType.ROWDATA, ByteString.EMPTY);
                logger.warn("table parser error : {}storeValue: {}", entry.toString(), rowChange.toString());
                return null;
            } else {
                Entry entry = createEntry(header, EntryType.ROWDATA, rowChange.toByteString());
                return entry;
            }
        } catch (Exception e) {
            throw new CanalParseException("parse row data failed.", e);
        }
    }

    private EntryPosition createPosition(LogHeader logHeader) {
        return new EntryPosition(logHeader.getLogFileName(), logHeader.getLogPos() - logHeader.getEventLen(), // startPos
            logHeader.getWhen() * 1000L,
            logHeader.getServerId()); // 记录到秒
    }

    private boolean parseOneRow(RowData.Builder rowDataBuilder, RowsLogEvent event, RowsLogBuffer buffer, BitSet cols,
                                boolean isAfter, TableMeta tableMeta) throws UnsupportedEncodingException {
        int columnCnt = event.getTable().getColumnCnt();
        ColumnInfo[] columnInfo = event.getTable().getColumnInfo();
        // mysql8.0针对set @@global.binlog_row_metadata='FULL' 可以记录部分的metadata信息
        boolean existOptionalMetaData = event.getTable().isExistOptionalMetaData();
        boolean tableError = false;
        // check table fileds count,只能处理加字段
        boolean existRDSNoPrimaryKey = false;

View on GitHub (pinned to 87be50e876)

Solutions

  1. Examine the cause exception (e.getCause()) in the CanalParseException to identify the specific parsing failure.
  2. Verify canal.instance.charset matches the database character set (commonly UTF-8).
  3. If caused by column mismatches, enable TSDB (canal.instance.tsdb.enable=true) for accurate historical DDL tracking.
  4. Enable filterTableError=true if the root cause is a stale table metadata mismatch.

Example fix

# before
canal.instance.charset=UTF-8
canal.instance.tsdb.enable=false

# after
canal.instance.charset=utf8mb4
canal.instance.tsdb.enable=true
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify charset configuration matches the database before starting
ResultSetPacket rs = mysqlConnection.query("SHOW VARIABLES LIKE 'character_set_database'");
String dbCharset = rs.getFieldValues().get(1);
if (!dbCharset.equalsIgnoreCase(configuredCharset)) {
    logger.warn("Charset mismatch: canal={}, db={}, row parsing may fail", configuredCharset, dbCharset);
}

Try / catch

try {
    Entry entry = parseRowsEvent(event);
} catch (CanalParseException e) {
    Throwable cause = e.getCause();
    logger.error("Row parsing failed at position {}, cause: {}",
        event.getHeader().getLogPos(), cause != null ? cause.getMessage() : "unknown", e);
    // Depending on cause type, skip the event or retry after metadata refresh
}

Prevention

When it happens

Trigger: Any exception during the row-parsing loop (parseOneRow calls, buffer reads, column building) that is not caught locally bubbles up to the try/catch in parseRowsEvent(). The cause exception reveals the specific failure: UnsupportedEncodingException, IndexOutOfBoundsException from buffer underflow, or data type conversion errors.

Common situations: The canal.instance.charset setting doesn't match the actual table character set, causing decoding errors. A JSON/BLOB column contains data that overflows the expected buffer. A column type in the binlog doesn't match the table metadata (DDL changed columns but cache wasn't refreshed). Network corruption produced a truncated event.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/9ac02677e3d8f3f8. Report an issue: GitHub.