alibaba/canal · error · IllegalArgumentException

!! Unknown Set len =

Error message

!! Unknown Set len = 

What it means

Thrown while decoding a MYSQL_TYPE_SET column. Like BIT, a SET is packed into the fewest bytes needed for its member count (nbits = (meta&0xFF)*8, len=(nbits+7)/8). The switch reads little-endian integers for byte lengths 1-8 only. MySQL SET is limited to 64 members, so len should never exceed 8; a value outside that range means corrupt metadata.

Source

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

                            value = buffer.getUint24();
                            break;
                        case 4:
                            value = buffer.getUint32();
                            break;
                        case 5:
                            value = buffer.getUlong40();
                            break;
                        case 6:
                            value = buffer.getUlong48();
                            break;
                        case 7:
                            value = buffer.getUlong56();
                            break;
                        case 8:
                            value = buffer.getUlong64();
                            break;
                        default:
                            throw new IllegalArgumentException("!! Unknown Set len = " + len);
                    }
                } else {
                    final int bit = buffer.getInt8();
                    // value = (bit != 0) ? Boolean.TRUE : Boolean.FALSE;
                    value = bit;
                }

                javaType = Types.BIT;
                length = len;
                break;
            }
            case LogEvent.MYSQL_TYPE_TINY_BLOB: {
                /*
                 * log_event.h : This enumeration value is only used internally and cannot exist
                 * in a binlog.
                 */
                logger.warn("MYSQL_TYPE_TINY_BLOB : This enumeration value is "
                            + "only used internally and cannot exist in a binlog!");

View on GitHub (pinned to 87be50e876)

Solutions

  1. Check the source SET column definition on the master (max 64 members).
  2. Validate the binlog at the reported position with mysqlbinlog.
  3. Upgrade Canal to match the master version.
  4. Exclude the table via canal.instance.filter.regex if unneeded.
Defensive patterns

Strategy: validation

Validate before calling

boolean isValidSetLen(int meta) {
    int nbits = (meta & 0xFF) * 8;
    int len = (nbits + 7) / 8;
    return len >= 1 && len <= 8; // MySQL SET max 64 members
}

Try / catch

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

Prevention

When it happens

Trigger: A Table_map_event advertises a SET column whose member count yields a byte length of 0 or > 8, which MySQL cannot create. Corrupt event or non-standard source.

Common situations: Binlog corruption; replicating from a forked engine that emits oversized SET metadata; schema drift between master and Canal's cached table map.

Related errors


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