alibaba/canal · error · CanalParseException

column size is not match for table:{},{} vs {}

Error message

column size is not match for table:{},{} vs {}

What it means

Thrown from parseOneRow() when the binlog's column count (columnInfo.length) exceeds the cached table metadata's field count (tableMeta.getFields().size()). This means the binlog event references more columns than Canal's metadata believes the table has — a clear sign that a DDL (column addition) happened but the metadata cache was not invalidated or TSDB didn't track it.

Source

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

                // 1. 新增一张临时表,将需要做ddl表的数据全量导入
                // 2. 在老表上建立I/U/D的trigger,增量的将数据插入到临时表
                // 3. 锁住应用请求,将临时表rename为老表的名字,完成增加字段的操作
                // 尝试做一次reload,可能因为ddl没有正确解析,或者使用了类似online ddl的操作
                // 因为online ddl没有对应表名的alter语法,所以不会有clear cache的操作
                tableMeta = getTableMeta(event.getTable().getDbName(), event.getTable().getTableName(), false, position);// 强制重新获取一次
                if (tableMeta == null) {
                    tableError = true;
                    if (!filterTableError) {
                        throw new CanalParseException("not found [" + event.getTable().getDbName() + "."
                                                      + event.getTable().getTableName() + "] in db , pls check!");
                    }
                }

                // 在做一次判断
                if (tableMeta != null && columnInfo.length > tableMeta.getFields().size()) {
                    tableError = true;
                    if (!filterTableError) {
                        throw new CanalParseException("column size is not match for table:" + tableMeta.getFullName()
                                                      + "," + columnInfo.length + " vs " + tableMeta.getFields().size());
                    }
                }
                // } else {
                // logger.warn("[" + event.getTable().getDbName() + "." +
                // event.getTable().getTableName()
                // + "] is no primary key , skip alibaba_rds_row_id column");
            }
        }

        for (int i = 0; i < columnCnt; i++) {
            ColumnInfo info = columnInfo[i];
            // mysql 5.6开始支持nolob/mininal类型,并不一定记录所有的列,需要进行判断
            if (!cols.get(i)) {
                continue;
            }

            if (existRDSNoPrimaryKey && i == columnCnt - 1 && info.type == LogEvent.MYSQL_TYPE_LONGLONG) {

View on GitHub (pinned to 87be50e876)

Solutions

  1. Enable TSDB: canal.instance.tsdb.enable=true and canal.instance.tsdb.dir=../conf/tsdb for persistent DDL history.
  2. If filterQueryDdl=true, either disable it or manually trigger a metadata refresh after known schema changes.
  3. Call tableMetaCache.clearTableMeta(schema, table) or restart Canal to force a full metadata reload.
  4. Verify the canal user can see the DDL events in the binlog (no binlog filtering on the MySQL side).

Example fix

# before — no TSDB, DDL filtered
canal.instance.tsdb.enable=false
canal.instance.filter.query.ddl=true

# after — TSDB enabled to track DDL history
canal.instance.tsdb.enable=true
canal.instance.tsdb.dir=../conf/tsdb
canal.instance.filter.query.ddl=false
Defensive patterns

Strategy: fallback

Try / catch

try {
    // parseOneRow with column check
    parseRowsEventForTableMeta(event);
} catch (CanalParseException e) {
    if (e.getMessage().contains("column size is not match")) {
        // Stale metadata — force a full cache invalidation and retry
        tableMetaCache.clearTableMeta(schema, table);
        logger.warn("Column mismatch detected, cache cleared for {}.{}, retrying", schema, table);
        // The next event will reload fresh metadata
    }
}

Prevention

When it happens

Trigger: After the forced reload in parseOneRow(), tableMeta is non-null but columnInfo.length > tableMeta.getFields().size(). The binlog was written with N columns but the current metadata only knows about N-k columns. This happens when ALTER TABLE ADD COLUMN occurred but Canal's DDL cache wasn't updated (the DDL event was filtered, missed, or came from a different connection).

Common situations: An ALTER TABLE added columns but Canal filtered out the DDL event (filterQueryDdl=true). The DDL was executed on a different schema name or through a stored procedure that Canal's parser didn't capture. TSDB is disabled so no historical DDL tracking exists. A replication filter on the MySQL side excluded the DDL but not the subsequent DML.

Related errors


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