alibaba/canal · error · IllegalArgumentException
parsing json value
Error message
parsing json value
What it means
Thrown during the second pass (print pass) of JSON diff parsing when the JSON value parsed from the diff payload has type Json_enum_type.ERROR. After calling JsonConversion.parse_value() on the value bytes within a REPLACE or INSERT operation, the result is checked for the ERROR sentinel type, indicating the value could not be parsed.
Source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/JsonDiffConversion.java:134
// Read path length
long path_length = buffer.getPackedLong();
// Print path
builder.append('\'').append(buffer.getFixString((int) path_length)).append('\'');
if (operation_int != DIFF_OPERATION_REMOVE) {
// Print comma between path and value
builder.append(", ");
// Read value length
long value_length = buffer.getPackedLong();
Json_Value jsonValue = JsonConversion.parse_value(buffer.getUint8(),
buffer,
value_length - 1,
charset);
buffer.forward((int) value_length - 1);
// Read value
if (jsonValue.m_type == Json_enum_type.ERROR) {
throw new IllegalArgumentException("parsing json value");
}
StringBuilder jsonBuilder = new StringBuilder();
jsonValue.toJsonString(jsonBuilder, charset);
builder.append(jsonBuilder);
}
// see https://github.com/alibaba/canal/pull/5018
if (buffer.position() - position >= len) {
builder.append(")");
break;
}
// Print closing parenthesis
if (!buffer.hasRemaining() || !Objects.equals(operation_names.get(diff_i + 1), operation_names.get(diff_i))) {
builder.append(")");
}
if (buffer.hasRemaining()) {View on GitHub (pinned to 87be50e876)
Solutions
- Check that value_length is > 1 before subtracting 1 to avoid underflow when cast to int.
- Verify the JSONB type byte within the value portion is a recognized constant (0x0-0xC, 0xF).
- Upgrade canal/dbsync to support the MySQL version producing the partial updates.
- Hex-dump the value bytes within the diff entry to inspect the type byte.
Example fix
// before
long value_length = buffer.getPackedLong();
Json_Value jsonValue = JsonConversion.parse_value(buffer.getUint8(), buffer, value_length - 1, charset);
// after: guard against underflow and ERROR
long value_length = buffer.getPackedLong();
if (value_length < 1) {
logger.warn("Invalid value_length {} in JSON diff, skipping", value_length);
return builder;
}
int valueType = buffer.getUint8();
Json_Value jsonValue = JsonConversion.parse_value(valueType, buffer, value_length - 1, charset);
if (jsonValue.m_type == Json_enum_type.ERROR) {
logger.warn("Failed to parse JSON diff value with type 0x{}", Integer.toHexString(valueType));
return builder;
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate value_length before parse_value is called by the library
// (this check must be done inside a fork or by wrapping the call)
// At minimum, ensure value_length > 1 to prevent underflow in value_length - 1
if (value_length < 1) {
logger.warn("JSON diff value_length underflow: {}", value_length);
return;
} Try / catch
try {
JsonDiffConversion.print_json_diff(buffer, len, columnName, columnIndex, charset);
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("parsing json value")) {
logger.warn("Embedded JSON value in diff could not be parsed, column={}", columnName);
}
throw e;
} Prevention
- Verify the embedded JSON type byte within the diff value is a recognized JSONB constant.
- Ensure value_length is at least 2 (type byte + at least 1 data byte) to avoid underflow.
- Upgrade canal/dbsync for MySQL 8.0 JSON format changes.
When it happens
Trigger: In print_json_diff's second-pass while loop, for non-REMOVE operations, the code reads value_length, then calls JsonConversion.parse_value with the value's type byte. If parse_value returns a Json_Value with m_type == ERROR (which can happen if the internal parsing produced a sentinel rather than throwing), this exception fires.
Common situations: An embedded JSON value within the diff uses an unsupported type byte, the value_length - 1 parameter underflows (value_length is 0, making it -1 when cast to int), or the value data is corrupt/truncated. MySQL 8.0+ introducing new JSONB types not handled by parse_value.
Related errors
- reading operation type (invalid operation code)
- skipping path
- reading json diff
- No such method: '{}' @ {}
- No such field: '{}' @ {}
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/06886e829bc9b65c.
Report an issue: GitHub.