alibaba/canal · error · TableIdNotFoundException

not found tableId:{}

Error message

not found tableId:{}

What it means

Thrown as TableIdNotFoundException when a RowsLogEvent arrives but event.getTable() returns null — meaning no TableMapLogEvent was seen for this tableId. The TableMapLogEvent is what maps a numeric tableId to schema/table/column metadata. Without it, Canal cannot interpret the row data.

Source

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

    private Entry parseRandLogEvent(RandLogEvent event) {
        if (filterQueryDml) {
            return null;
        }

        return buildQueryEntry(event.getQuery(), event.getHeader());
    }

    private Entry parseXidEvent(XidLogEvent event) {
        TransactionEnd transactionEnd = createTransactionEnd(event.getXid());
        Header header = createHeader(event.getHeader(), "", "", null);
        return createEntry(header, EntryType.TRANSACTIONEND, transactionEnd.toByteString());
    }

    public TableMeta parseRowsEventForTableMeta(RowsLogEvent event) {
        TableMapLogEvent table = event.getTable();
        if (table == null) {
            // tableId对应的记录不存在
            throw new TableIdNotFoundException("not found tableId:" + event.getTableId());
        }

        boolean isHeartBeat = isAliSQLHeartBeat(table.getDbName(), table.getTableName());
        boolean isRDSHeartBeat = tableMetaCache.isOnRDS() && isRDSHeartBeat(table.getDbName(), table.getTableName());

        String fullname = table.getDbName() + "." + table.getTableName();
        // check name filter
        if (nameFilter != null && !nameFilter.filter(fullname)) {
            return null;
        }
        if (nameBlackFilter != null && nameBlackFilter.filter(fullname)) {
            return null;
        }

        // if (isHeartBeat || isRDSHeartBeat) {
        // // 忽略rds模式的mysql.ha_health_check心跳数据
        // return null;
        // }

View on GitHub (pinned to 87be50e876)

Solutions

  1. Ensure Canal starts from a transaction boundary (BEGIN event), not an arbitrary offset within a transaction.
  2. If the position is specified manually, adjust it to the start of the next complete transaction.
  3. Enable GTID-based positioning so Canal can correctly resume from transaction boundaries after restart.
  4. If the error is transient (only first event after restart), consider catching TableIdNotFoundException and letting Canal skip to the next transaction.

Example fix

# before — manual position in the middle of a transaction
canal.instance.gtidenabled=false
canal.instance.master.position=mysql-bin.000005:9876

# after — use GTID for safe transaction-boundary resumption
canal.instance.gtidenabled=true
canal.instance.gtid=3E4FA457-2A57-11E7-8F2A-1234567890AB:1-999999
Defensive patterns

Strategy: retry

Try / catch

try {
    TableMeta meta = parseRowsEventForTableMeta(event);
} catch (TableIdNotFoundException e) {
    // Missing TABLE_MAP event — likely started mid-transaction
    // Skip this event and advance to the next transaction boundary
    logger.warn("TableId {} not found, skipping event — likely mid-transaction start", event.getTableId(), e);
    // Advance position to skip the incomplete transaction
}

Prevention

When it happens

Trigger: parseRowsEventForTableMeta() is called on a RowsLogEvent whose TableMapLogEvent was not received. This occurs when Canal starts reading from a binlog position that is in the middle of a transaction (after the TABLE_MAP event but before the WRITE/UPDATE/DELETE_ROWS event), or when the TABLE_MAP event was on a previous binlog file that was rotated out of the in-memory map.

Common situations: Canal restarts and resumes from a position inside an incomplete transaction. The binlog rotation happened between TABLE_MAP and ROWS events. A very long transaction spans multiple binlog files and Canal reconnects mid-way. The starting position in instance.properties points to a row event offset rather than a transaction boundary.

Related errors


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