alibaba/canal · error · IllegalArgumentException
!! Unknown JSON packlen =
Error message
!! Unknown JSON packlen =
What it means
Thrown while decoding a MYSQL_TYPE_JSON column. Like BLOB, the metadata (meta) is the length-prefix size in bytes (1-4). The switch reads the data length as uint8/16/24/32; any other meta value is invalid. MySQL JSON is stored as a blob with a 1-4 byte length prefix, so meta outside 1-4 indicates corrupt or unrecognized table-map metadata.
Source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogBuffer.java:1056
switch (meta) {
case 1: {
len = buffer.getUint8();
break;
}
case 2: {
len = buffer.getUint16();
break;
}
case 3: {
len = buffer.getUint24();
break;
}
case 4: {
len = (int) buffer.getUint32();
break;
}
default:
throw new IllegalArgumentException("!! Unknown JSON packlen = " + meta);
}
if (partialBits.get(1)) {
// print_json_diff
int position = buffer.position();
try {
// https://github.com/alibaba/canal/pull/5018
StringBuilder builder = JsonDiffConversion
.print_json_diff(buffer, len, columnName, columnIndex, charset);
value = builder.toString();
buffer.position(position + len);
} catch (IllegalArgumentException e) {
buffer.position(position);
// print_json_diff failed, fallback to parse_value
parseJsonFromFullValue(len);
}
} else {
parseJsonFromFullValue(len);
View on GitHub (pinned to 87be50e876)
Solutions
- Upgrade Canal to a release supporting the master's JSON binlog encoding (partial-update / JSON diff was added around PR #5018).
- Confirm the JSON column exists on the master and Canal's schema cache is current.
- Validate the binlog position with mysqlbinlog --hexdump.
- Filter the table if JSON data is not required.
Defensive patterns
Strategy: validation
Validate before calling
boolean isValidJsonPacklen(int meta) {
return meta >= 1 && meta <= 4;
} Try / catch
try {
buffer.fetchValue(name, index, type, meta, isBinary);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("!! Unknown JSON packlen")) {
logger.warn("Corrupt JSON packlen meta={} in tableId={}, skipping column", meta, tableId);
} else throw e;
} Prevention
- Use a Canal build that supports the master's JSON binlog encoding (incl. partial-update / JSON diff, PR #5018).
- Validate the JSON column schema matches Canal's cached table map.
- Filter JSON tables if the downstream does not need them.
When it happens
Trigger: A Table_map_event declares a JSON column with a length-prefix meta of 0 or > 4, or Canal is too old to read the JSON encoding a newer MySQL emits.
Common situations: Replicating from MySQL 5.7+/8.0 with a Canal build predating JSON partial-update support; binlog corruption; a forked JSON diff format (see the partialBits.get(1) branch referencing PR #5018).
Related errors
- !! Don't know how to handle column type=%d meta=%d (%04X)
- !! Unknown Bit len =
- !! Unknown ENUM packlen =
- !! Unknown Set len =
- !! Unknown BLOB packlen =
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/dd3ec0548c18273d.
Report an issue: GitHub.