alibaba/canal · error · IllegalArgumentException

skipping path

Error message

skipping path

What it means

Thrown during the first pass of JSON diff parsing when the packed-long path length exceeds the total diff payload length (len). After reading the operation code, the code reads a variable-length packed integer for the path length; if this path_length is greater than the overall diff size, the data is corrupt or misaligned.

Source

Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/JsonDiffConversion.java:57

    public static StringBuilder print_json_diff(LogBuffer buffer, long len, String columnName, int columnIndex,
                                                String charsetName) {
        return print_json_diff(buffer, len, columnName, columnIndex, Charset.forName(charsetName));
    }

    public static StringBuilder print_json_diff(LogBuffer buffer, long len, String columnName, int columnIndex,
                                                Charset charset) {
        int position = buffer.position();
        List<String> operation_names = new ArrayList<>();
        while (buffer.hasRemaining()) {
            int operation_int = buffer.getUint8();
            if (operation_int >= JSON_DIFF_OPERATION_COUNT) {
                throw new IllegalArgumentException("reading operation type (invalid operation code)");
            }

            // skip path
            long path_length = buffer.getPackedLong();
            if (path_length > len) {
                throw new IllegalArgumentException("skipping path");
            }

            // compute operation name
            byte[] lastP = buffer.getData(buffer.position() + (int) path_length - 1, 1);
            String operation_name = json_diff_operation_name(operation_int, lastP[0]);
            operation_names.add(operation_name);

            buffer.forward((int) path_length);
            // skip value
            if (operation_int != DIFF_OPERATION_REMOVE) {
                long value_length = buffer.getPackedLong();
                if (value_length > len) {
                    throw new IllegalArgumentException("skipping path");
                }

                buffer.forward((int) value_length);
            }

View on GitHub (pinned to 87be50e876)

Solutions

  1. Verify the len parameter passed to print_json_diff matches the actual column value length from the row event.
  2. Trace buffer position from the row event header to ensure no prior column consumed incorrect byte counts.
  3. Hex-dump the diff payload region to inspect the packed path_length value.
  4. Skip the corrupt diff and re-synchronize replication from the last known-good binlog position.
Defensive patterns

Strategy: validation

Validate before calling

// The library checks path_length > len internally.
// Callers can pre-validate by ensuring the diff payload length matches the column value size.
if (len > buffer.remaining()) {
    logger.warn("Diff payload length {} exceeds buffer remaining {}", len, buffer.remaining());
    return;
}

Try / catch

try {
    JsonDiffConversion.print_json_diff(buffer, len, columnName, columnIndex, charset);
} catch (IllegalArgumentException e) {
    logger.warn("JSON diff path length exceeds payload in column {}, pos={}", columnName, buffer.position(), e);
}

Prevention

When it happens

Trigger: Calling print_json_diff() where, after reading a valid operation code, the path_length obtained from buffer.getPackedLong() exceeds the len parameter. This means the declared path would extend beyond the diff payload boundary.

Common situations: Binlog corruption truncating the diff payload, buffer position offset from an earlier parse consuming too few or too many bytes, or a malformed JSON partial update event from a bug in the MySQL server or an intermediate proxy that modifies binlog events.

Related errors


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