alibaba/canal · error · IOException

Error INT_RESULT length:

Error message

Error INT_RESULT length: 

What it means

Thrown while decoding a UserVarLogEvent whose value type is INT_RESULT. MySQL stores INT user variables as either 4-byte (32-bit) or 8-byte (64-bit) values. If the declared valueLen is neither 4 nor 8, the payload is structurally invalid and an IOException is thrown. This guards against truncation or corruption of the user-variable value section.

Solutions

  1. Inspect the binlog at the reported position with mysqlbinlog to confirm the UserVar event is intact.
  2. If the binlog is corrupt, reseed Canal from a valid position.
  3. Upgrade Canal to match the master version.
  4. Avoid relying on user-variable events if the replication target does not need them.
Defensive patterns

Strategy: try-catch

Validate before calling

boolean isValidIntResultLen(int valueLen) {
    return valueLen == 4 || valueLen == 8;
}

Try / catch

try {
    userVarEvent.parse();
} catch (IOException e) {
    if (e.getMessage().startsWith("Error INT_RESULT length")) {
        logger.warn("Corrupt INT user variable, skipping event");
        // skip / null the value
    } else throw e;
}

Prevention

When it happens

Trigger: A UserVarLogEvent with type INT_RESULT and a value length other than 4 or 8 bytes. Produced by binlog corruption, truncation, or a source that mis-encodes user-variable events.

Common situations: Replicating SET @var = <bigint> statements from a corrupted binlog; a partial binlog read; a MySQL fork with non-standard user-variable encoding.

Related errors


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

Appendix: source

Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/UserVarLogEvent.java:96

            charsetNumber = 63; /* binary */
            value = null;
        } else {
            type = buffer.getInt8(); // UV_VAL_IS_NULL
            charsetNumber = (int) buffer.getUint32(); // buf + UV_VAL_TYPE_SIZE
            final int valueLen = (int) buffer.getUint32(); // buf +
                                                           // UV_CHARSET_NUMBER_SIZE
            final int limit = buffer.limit(); /* for restore */
            buffer.limit(buffer.position() + valueLen);

            /* @see User_var_log_event::print */
            switch (type) {
                case REAL_RESULT:
                    value = Double.valueOf(buffer.getDouble64()); // float8get
                    break;
                case INT_RESULT:
                    if (valueLen == 8) value = Long.valueOf(buffer.getLong64()); // !uint8korr
                    else if (valueLen == 4) value = Long.valueOf(buffer.getUint32());
                    else throw new IOException("Error INT_RESULT length: " + valueLen);
                    break;
                case DECIMAL_RESULT:
                    final int precision = buffer.getInt8();
                    final int scale = buffer.getInt8();
                    value = buffer.getDecimal(precision, scale); // bin2decimal
                    break;
                case STRING_RESULT:
                    Charset charset = CharsetConversion.getNioCharset(charsetNumber);
                    value = buffer.getFixString(valueLen, charset);
                    break;
                case ROW_RESULT:
                    // this seems to be banned in MySQL altogether
                    throw new IOException("ROW_RESULT is unsupported");
                default:
                    value = null;
                    break;
            }
            buffer.limit(limit);

View on GitHub (pinned to 87be50e876)