{"record":{"id":"963dfe8f3a88940a","repo":"alibaba/canal","slug":"not-found-tableid-963dfe","errorCode":null,"errorMessage":"not found tableId:{}","messagePattern":"not found tableId:(.+?)","errorType":"exception","errorClass":"TableIdNotFoundException","httpStatus":null,"severity":"error","filePath":"parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/dbsync/LogEventConvert.java","lineNumber":458,"sourceCode":"    private Entry parseRandLogEvent(RandLogEvent event) {\n        if (filterQueryDml) {\n            return null;\n        }\n\n        return buildQueryEntry(event.getQuery(), event.getHeader());\n    }\n\n    private Entry parseXidEvent(XidLogEvent event) {\n        TransactionEnd transactionEnd = createTransactionEnd(event.getXid());\n        Header header = createHeader(event.getHeader(), \"\", \"\", null);\n        return createEntry(header, EntryType.TRANSACTIONEND, transactionEnd.toByteString());\n    }\n\n    public TableMeta parseRowsEventForTableMeta(RowsLogEvent event) {\n        TableMapLogEvent table = event.getTable();\n        if (table == null) {\n            // tableId对应的记录不存在\n            throw new TableIdNotFoundException(\"not found tableId:\" + event.getTableId());\n        }\n\n        boolean isHeartBeat = isAliSQLHeartBeat(table.getDbName(), table.getTableName());\n        boolean isRDSHeartBeat = tableMetaCache.isOnRDS() && isRDSHeartBeat(table.getDbName(), table.getTableName());\n\n        String fullname = table.getDbName() + \".\" + table.getTableName();\n        // check name filter\n        if (nameFilter != null && !nameFilter.filter(fullname)) {\n            return null;\n        }\n        if (nameBlackFilter != null && nameBlackFilter.filter(fullname)) {\n            return null;\n        }\n\n        // if (isHeartBeat || isRDSHeartBeat) {\n        // // 忽略rds模式的mysql.ha_health_check心跳数据\n        // return null;\n        // }","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/dbsync/LogEventConvert.java#L440-L476","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure Canal starts from a transaction boundary (BEGIN event), not an arbitrary offset within a transaction.","If the position is specified manually, adjust it to the start of the next complete transaction.","Enable GTID-based positioning so Canal can correctly resume from transaction boundaries after restart.","If the error is transient (only first event after restart), consider catching TableIdNotFoundException and letting Canal skip to the next transaction."],"exampleFix":"# before — manual position in the middle of a transaction\ncanal.instance.gtidenabled=false\ncanal.instance.master.position=mysql-bin.000005:9876\n\n# after — use GTID for safe transaction-boundary resumption\ncanal.instance.gtidenabled=true\ncanal.instance.gtid=3E4FA457-2A57-11E7-8F2A-1234567890AB:1-999999","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    TableMeta meta = parseRowsEventForTableMeta(event);\n} catch (TableIdNotFoundException e) {\n    // Missing TABLE_MAP event — likely started mid-transaction\n    // Skip this event and advance to the next transaction boundary\n    logger.warn(\"TableId {} not found, skipping event — likely mid-transaction start\", event.getTableId(), e);\n    // Advance position to skip the incomplete transaction\n}","preventionTips":["Use GTID-based positioning so Canal always resumes at transaction boundaries after restart.","Avoid manually specifying binlog positions that point inside a transaction.","When restarting Canal, let it auto-discover the position from zookeeper/meta mode rather than hardcoding."],"tags":["mysql","binlog","table-map","tableid","row-event"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}