{"record":{"id":"6cf79284cc676811","repo":"alibaba/canal","slug":"not-found-tableid","errorCode":null,"errorMessage":"not found tableId:","messagePattern":"not found tableId:","errorType":"exception","errorClass":"TableIdNotFoundException","httpStatus":null,"severity":"critical","filePath":"dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogEvent.java","lineNumber":203,"sourceCode":"            // mariadb compress log event\n            // see https://github.com/alibaba/canal/issues/4388\n            buffer = buffer.uncompressBuf();\n            dataSize = buffer.limit();\n            // rewrite type\n            if (postHeaderLen == FormatDescriptionLogEvent.ROWS_HEADER_LEN_V2) {\n                header.type = header.type - WRITE_ROWS_COMPRESSED_EVENT + WRITE_ROWS_EVENT;\n            } else {\n                header.type = header.type - WRITE_ROWS_COMPRESSED_EVENT_V1 + WRITE_ROWS_EVENT_V1;\n            }\n        }\n        rowsBuf = buffer.duplicate(dataSize);\n    }\n\n    public final void fillTable(LogContext context) {\n        table = context.getTable(tableId);\n\n        if (table == null) {\n            throw new TableIdNotFoundException(\"not found tableId:\" + tableId);\n        }\n\n        // end of statement check:\n        if ((flags & RowsLogEvent.STMT_END_F) != 0) {\n            // Now is safe to clear ignored map (clear_tables will also\n            // delete original table map events stored in the map).\n            context.clearAllTables();\n        }\n\n        int jsonColumnCount = 0;\n        int columnCnt = table.getColumnCnt();\n        ColumnInfo[] columnInfo = table.getColumnInfo();\n        for (int i = 0; i < columnCnt; i++) {\n            ColumnInfo info = columnInfo[i];\n            if (info.type == LogEvent.MYSQL_TYPE_JSON) {\n                jsonColumnCount++;\n            }\n        }","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogEvent.java#L185-L221","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    rowsLogEvent.fillTable(logContext);\n} catch (TableIdNotFoundException e) {\n    logger.error(\"Table map missing for tableId={} at {}:{}; starting mid-transaction? Reposition at a BEGIN.\",\n        rowsLogEvent.getTableId(),\n        logContext.getLogFilename(), rowsLogEvent.getHeader().getLogPos());\n    // reposition the dump at the next transaction boundary or skip the event\n}","preventionTips":["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."],"tags":["binlog","rows-event","table-map","table-id","parsing"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}