alibaba/canal · error · IllegalArgumentException

!! Unknown ENUM packlen =

Error message

!! Unknown ENUM packlen = 

What it means

Thrown while decoding a MYSQL_TYPE_ENUM column. ENUM values are stored as a packed integer of 1 byte (enum <= 255 values) or 2 bytes. The switch only handles len 1 and 2; any other length is impossible for a valid MySQL ENUM and indicates corrupt table-map metadata. The comment notes MYSQL_TYPE_ENUM is internal-only and should not appear in a binlog in modern MySQL, so hitting this also implies a legacy or forked event stream.

Source

Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogBuffer.java:859

                javaType = Types.VARCHAR; // Types.INTEGER;
                length = 1;
                break;
            }
            case LogEvent.MYSQL_TYPE_ENUM: {
                final int int32;
                /*
                 * log_event.h : This enumeration value is only used internally and cannot exist
                 * in a binlog.
                 */
                switch (len) {
                    case 1:
                        int32 = buffer.getUint8();
                        break;
                    case 2:
                        int32 = buffer.getUint16();
                        break;
                    default:
                        throw new IllegalArgumentException("!! Unknown ENUM packlen = " + len);
                }
                // logger.warn("MYSQL_TYPE_ENUM : This enumeration value is "
                // + "only used internally and cannot exist in a binlog!");
                value = valueOf(int32);
                javaType = Types.INTEGER;
                length = len;
                break;
            }
            case LogEvent.MYSQL_TYPE_SET: {
                final int nbits = (meta & 0xFF) * 8;
                len = (nbits + 7) / 8;
                if (nbits > 1) {
                    // byte[] bits = new byte[len];
                    // buffer.fillBytes(bits, 0, len);
                    // 转化为unsign long
                    switch (len) {
                        case 1:
                            value = buffer.getUint8();

View on GitHub (pinned to 87be50e876)

Solutions

  1. Confirm the master MySQL version; ENUM in binlogs typically arrives as MYSQL_TYPE_STRING in modern versions.
  2. Inspect the Table_map event with mysqlbinlog --hexdump to verify the column metadata.
  3. Upgrade Canal to a build that handles the master's encoding.
  4. Filter the table if the ENUM column is not required downstream.
Defensive patterns

Strategy: validation

Validate before calling

boolean isValidEnumPacklen(int len) {
    return len == 1 || len == 2;
}

Try / catch

try {
    buffer.fetchValue(name, index, type, meta, isBinary);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("!! Unknown ENUM packlen")) {
        logger.warn("Corrupt ENUM packlen={} in tableId={}, skipping column", len, tableId);
    } else throw e;
}

Prevention

When it happens

Trigger: A Table_map_event declares ENUM with a storage length other than 1 or 2 bytes, or an event stream from an old MySQL that still writes MYSQL_TYPE_ENUM into the binlog.

Common situations: Replicating from a very old MySQL 5.0/5.1 stream; binlog corruption; a MySQL fork that reuses the ENUM type code differently.

Related errors


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