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

  1. Upgrade Canal to a release supporting the master's JSON binlog encoding (partial-update / JSON diff was added around PR #5018).
  2. Confirm the JSON column exists on the master and Canal's schema cache is current.
  3. Validate the binlog position with mysqlbinlog --hexdump.
  4. 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

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


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