alibaba/canal · error · CanalParseException

not found [{}] in db , pls check!

Error message

not found [{}] in db , pls check!

What it means

Thrown from parseRowsEventForTableMeta() when tableMetaCache.getTableMeta() returns null for a table that exists in the binlog stream. The TableMapLogEvent identified a schema.table, but Canal could not load its metadata from the connected database. Unless filterTableError is true, this is fatal for the current event.

Source

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

            // 处理rds模式的mysql.ha_health_check心跳数据
            // 主要RDS的心跳表基本无权限,需要mock一个tableMeta
            FieldMeta idMeta = new FieldMeta("id", "bigint(20)", true, false, "0");
            FieldMeta typeMeta = new FieldMeta("type", "char(1)", false, true, "0");
            tableMeta = new TableMeta(table.getDbName(), table.getTableName(), Arrays.asList(idMeta, typeMeta));
        } else if (isHeartBeat) {
            // 处理alisql模式的test.heartbeat心跳数据
            // 心跳表基本无权限,需要mock一个tableMeta
            FieldMeta idMeta = new FieldMeta("id", "smallint(6)", false, true, null);
            FieldMeta typeMeta = new FieldMeta("ts", "int(11)", true, false, null);
            tableMeta = new TableMeta(table.getDbName(), table.getTableName(), Arrays.asList(idMeta, typeMeta));
        }

        EntryPosition position = createPosition(event.getHeader());
        if (tableMetaCache != null && tableMeta == null) {// 入错存在table meta
            tableMeta = getTableMeta(table.getDbName(), table.getTableName(), true, position);
            if (tableMeta == null) {
                if (!filterTableError) {
                    throw new CanalParseException("not found [" + fullname + "] in db , pls check!");
                }
            }
        }

        return tableMeta;
    }

    public Entry parseRowsEvent(RowsLogEvent event) {
        return parseRowsEvent(event, null);
    }

    public void parseTableMapEvent(TableMapLogEvent event) {
        try {
            String charsetDbName = new String(event.getDbName().getBytes(ISO_8859_1), charset);
            event.setDbname(charsetDbName);

            String charsetTbName = new String(event.getTableName().getBytes(ISO_8859_1), charset);
            event.setTblname(charsetTbName);

View on GitHub (pinned to 87be50e876)

Solutions

  1. Set canal.instance.filter.table.error = true in instance.properties to skip events for missing tables instead of aborting.
  2. Grant SELECT on the relevant databases: GRANT SELECT ON mydb.* TO 'canal'@'%';
  3. If the table was intentionally dropped, ensure Canal processes the DROP DDL event so its metadata cache is invalidated.
  4. Enable TSDB (canal.instance.tsdb.enable=true) so historical table metadata is preserved for dropped tables.

Example fix

# before
canal.instance.filter.table.error=false

# after
canal.instance.filter.table.error=true
canal.instance.tsdb.enable=true
Defensive patterns

Strategy: validation

Validate before calling

// Before processing, verify the table exists and is accessible
try {
    mysqlConnection.query("SELECT 1 FROM " + schema + "." + table + " LIMIT 1");
} catch (Exception e) {
    logger.warn("Table {}.{} not accessible, enabling filterTableError recommended", schema, table);
}

Try / catch

try {
    TableMeta meta = parseRowsEventForTableMeta(event);
} catch (CanalParseException e) {
    if (e.getMessage().contains("not found") && e.getMessage().contains("in db")) {
        if (filterTableError) {
            logger.warn("Table not found, skipping row event: {}", fullname);
            return null;
        }
    }
    throw e;
}

Prevention

When it happens

Trigger: getTableMeta(schema, table, true, position) is called and returns null. This happens when 'show create table' and 'desc' both fail for the table — the table was dropped, renamed, or the canal user lacks SELECT privileges on it. Also occurs when the table is a temporary table or exists only in a different schema context.

Common situations: The table was dropped between the binlog event being written and Canal processing it. The table was renamed via DDL that Canal's parser missed. The canal user has replication privileges but not SELECT on the specific database. The table is in a schema that was dropped. The table is a MySQL internal/temporary table.

Related errors


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