alibaba/canal · critical · TableIdNotFoundException
not found tableId:
Error message
not found tableId:
What it means
Thrown by RowsLogEvent.fillTable when context.getTable(tableId) returns null. Every rows event (WRITE/UPDATE/DELETE) must be preceded by a TABLE_MAP event that registers the tableId with its column metadata in the LogContext. If no prior TABLE_MAP event was seen — or the map was cleared (clearAllTables runs on STMT_END_F) before this event — the lookup fails and TableIdNotFoundException aborts parsing.
Source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogEvent.java:203
// mariadb compress log event
// see https://github.com/alibaba/canal/issues/4388
buffer = buffer.uncompressBuf();
dataSize = buffer.limit();
// rewrite type
if (postHeaderLen == FormatDescriptionLogEvent.ROWS_HEADER_LEN_V2) {
header.type = header.type - WRITE_ROWS_COMPRESSED_EVENT + WRITE_ROWS_EVENT;
} else {
header.type = header.type - WRITE_ROWS_COMPRESSED_EVENT_V1 + WRITE_ROWS_EVENT_V1;
}
}
rowsBuf = buffer.duplicate(dataSize);
}
public final void fillTable(LogContext context) {
table = context.getTable(tableId);
if (table == null) {
throw new TableIdNotFoundException("not found tableId:" + tableId);
}
// end of statement check:
if ((flags & RowsLogEvent.STMT_END_F) != 0) {
// Now is safe to clear ignored map (clear_tables will also
// delete original table map events stored in the map).
context.clearAllTables();
}
int jsonColumnCount = 0;
int columnCnt = table.getColumnCnt();
ColumnInfo[] columnInfo = table.getColumnInfo();
for (int i = 0; i < columnCnt; i++) {
ColumnInfo info = columnInfo[i];
if (info.type == LogEvent.MYSQL_TYPE_JSON) {
jsonColumnCount++;
}
}View on GitHub (pinned to 87be50e876)
Solutions
- Start Canal at a transaction boundary (BEGIN/Format_description or a GTID event) so TABLE_MAP events precede rows events.
- Ensure table filtering does not drop TABLE_MAP events for tables whose rows you still receive — adjust canal.instance.filter.regex/black to be consistent.
- If the position is stale or corrupt, reset canal.instance.master.position (or the GTID) to a known-good start and clear the stored position.
- Upgrade Canal; older versions had bugs clearing the table map too eagerly on STMT_END_F.
Defensive patterns
Strategy: try-catch
Try / catch
try {
rowsLogEvent.fillTable(logContext);
} catch (TableIdNotFoundException e) {
logger.error("Table map missing for tableId={} at {}:{}; starting mid-transaction? Reposition at a BEGIN.",
rowsLogEvent.getTableId(),
logContext.getLogFilename(), rowsLogEvent.getHeader().getLogPos());
// reposition the dump at the next transaction boundary or skip the event
} Prevention
- Always start Canal at a transaction boundary (BEGIN / GTID / Format_description) so TABLE_MAP events precede rows events.
- Keep table-map filtering consistent — do not filter out a TABLE_MAP for tables whose rows you still receive.
- After an unclean restart, reset the stored position to a known-good boundary.
When it happens
Trigger: Canal starts mid-binlog at a position inside a transaction (after the TABLE_MAP but at a rows event); a TABLE_MAP event was filtered out or dropped; the LogContext was reset between the map event and the rows event; replicating a rows event whose tableId was never mapped because filtering excluded its table map.
Common situations: Starting Canal at a position that is not a transaction boundary; a binlog rotation or dump restart that loses buffered table-map state; filtering (canal.instance.filter) that skips the TABLE_MAP event but not its rows events; binlog corruption dropping a TABLE_MAP event.
Related errors
- Read error:
- !! Don't know how to handle column type=%d meta=%d (%04X)
- !! Unknown Bit len =
- !! Unknown ENUM packlen =
- !! Unknown Set len =
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/6cf79284cc676811.
Report an issue: GitHub.