alibaba/canal · error · IllegalArgumentException
!! Unknown Bit len =
Error message
!! Unknown Bit len =
What it means
Thrown while decoding a MYSQL_TYPE_BIT column. The metadata word gives bit_len and bytes_in_rec; nbits is recomputed as ((meta>>8)*8)+(meta&0xff), and len is the byte length (nbits+7)/8. The switch reads big-endian integer values for byte lengths 1 through 8 only. MySQL BIT columns are capped at 64 bits (len <= 8), so a len outside 1-8 indicates a corrupt or maliciously crafted table-map metadata.
Source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogBuffer.java:419
value = buffer.getBeUint24();
break;
case 4:
value = buffer.getBeUint32();
break;
case 5:
value = buffer.getBeUlong40();
break;
case 6:
value = buffer.getBeUlong48();
break;
case 7:
value = buffer.getBeUlong56();
break;
case 8:
value = buffer.getBeUlong64();
break;
default:
throw new IllegalArgumentException("!! Unknown Bit len = " + len);
}
} else {
final int bit = buffer.getInt8();
// value = (bit != 0) ? Boolean.TRUE : Boolean.FALSE;
value = bit;
}
javaType = Types.BIT;
length = nbits;
break;
}
case LogEvent.MYSQL_TYPE_TIMESTAMP: {
// MYSQL DataTypes: TIMESTAMP
// range is '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07'
// UTC
// A TIMESTAMP cannot represent the value '1970-01-01 00:00:00'
// because that is equivalent to 0 seconds from the epoch and
// the value 0 is reserved for representing '0000-00-00
// 00:00:00', the “zero” TIMESTAMP value.
View on GitHub (pinned to 87be50e876)
Solutions
- Verify the source table's BIT column width on the master (must be <= 64).
- Run mysqlbinlog on the offending position to confirm the metadata is intact; reseed Canal from a valid position if corrupt.
- Upgrade Canal in case a newer MySQL encoding of BIT metadata is misread by an older parser.
- Exclude the affected table via canal.instance.filter.regex if the column is not needed.
Example fix
// before
default:
throw new IllegalArgumentException("!! Unknown Bit len = " + len);
// after: clamp instead of aborting replication
default:
logger.warn("Unexpected BIT byte length {}, reading raw bytes", len);
byte[] bits = new byte[len];
buffer.fillBytes(bits, 0, len);
value = bits; Defensive patterns
Strategy: validation
Validate before calling
static final int MAX_BIT_BYTES = 8; // 64 bits max
boolean isValidBitLen(int meta) {
int nbits = ((meta >> 8) * 8) + (meta & 0xff);
int len = (nbits + 7) / 8;
return len >= 1 && len <= MAX_BIT_BYTES;
} Try / catch
try {
buffer.fetchValue(name, index, type, meta, isBinary);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("!! Unknown Bit len")) {
logger.warn("Corrupt BIT metadata meta={} in tableId={}, skipping column", meta, tableId);
} else throw e;
} Prevention
- Verify BIT column widths on the master are <= 64 bits.
- Monitor for binlog corruption on the master's storage.
- Keep Canal and master versions aligned.
When it happens
Trigger: A Table_map_event for a row event declares a BIT column whose computed byte length is 0 or exceeds 8 (i.e. > 64 bits), which MySQL itself cannot create. Caused by binlog corruption or a forged event.
Common situations: Binlog file corruption; replicating from a non-standard MySQL-compatible store that emits oversized BIT metadata; disk-level bit rot in the binlog.
Related errors
- !! Don't know how to handle column type=%d meta=%d (%04X)
- !! Unknown ENUM packlen =
- !! Unknown Set len =
- !! Unknown BLOB packlen =
- !! Unknown JSON packlen =
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/677c172a820a5ceb.
Report an issue: GitHub.