alibaba/canal · error · IOException
Read error:
Error message
Read error:
What it means
Thrown while parsing the status-variable block of a MySQL Query_log_event (e.g. BEGIN/COMMIT/DDL). The parser loops over status-var codes (Q_* constants) and this catch wraps any RuntimeException — buffer underflow, unknown code, or malformed length — into an IOException tagged with the offending status-var code name via findCodeName(code). The preceding default branch already logs-and-skips unknown codes, so this catch fires on structurally corrupt data: a truncated or misaligned status-var payload that breaks buffer reads.
Source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/QueryLogEvent.java:913
}
}
break;
case Q_OPT_INDEX_FORMAT_PANDA_ENABLED:
// *start++ = thd->variables.opt_index_format_panda_enabled;
buffer.forward(1);
break;
default:
/*
* That's why you must write status vars in growing
* order of code
*/
logger.error("Query_log_event has unknown status vars (first has code: " + code
+ "), skipping the rest of them");
return; // Break loop
}
}
} catch (RuntimeException e) {
throw new IOException("Read " + findCodeName(code) + " error: " + e.getMessage(), e);
}
}
public final String getUser() {
return user;
}
public final String getHost() {
return host;
}
public final String getQuery() {
return query;
}
public final String getCatalog() {
return catalog;
}View on GitHub (pinned to 87be50e876)
Solutions
- Upgrade Canal to a release that supports the status-var codes your MySQL version emits (check the Q_* cases in QueryLogEvent around the throwing line).
- If the master is a fork, confirm the Canal build matches it (lizard/panda Q_LIZARD_* and Q_OPT_* branches must be present).
- Inspect the binlog with mysqlbinlog at the reported position to confirm the event is structurally valid; if corrupt, skip the position with canal.instance.master.position or reseed from a known-good position.
- If the code is genuinely unsupported, the existing default-branch logger.error already skips remaining vars — a RuntimeException before that means truncation, so verify binlog file integrity (checksum, file size vs index).
Example fix
// before: runtime exception during status-var read escapes as IOException
// after (defensive read, guard each code handler against remaining bytes):
int remaining = buffer.remaining();
if (code == Q_WHATEVER && remaining < needed) {
logger.warn("Q_WHATEVER truncated (need {}, have {}), skipping", needed, remaining);
return;
} Defensive patterns
Strategy: try-catch
Try / catch
// At the CanalEventSink / parser boundary
try {
eventSink.consume(event);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Read ")) {
// status-var parse failure — log position and skip the event
logger.error("Status-var parse failure at {}:{}: {}",
logContext.getLogFilename(), event.getHeader().getLogPos(), e.getMessage());
// advance past this event to continue replication
} else {
throw e;
}
} Prevention
- Keep Canal version >= the MySQL major version it replicates from so all Q_* status-var codes are recognized.
- If replicating from a fork (AliSQL), use the matching Canal fork build.
- Monitor binlog integrity (checksums) on the master.
When it happens
Trigger: A QueryLogEvent whose status-vars section is shorter than the declared length, contains a code whose handler reads more bytes than remain, or originates from a MySQL/MariaDB fork (lizard, panda, recycle-bin) emitting a code the reader only partially understands. The exception surfaces at parse time, before the event is handed to a Canal instance.
Common situations: Canal version older than the upstream MySQL that produced the binlog; replicating from a patched MySQL fork (AliSQL lizard/panda) without the matching Canal build; binlog corruption on disk or over a flaky network; a partial binlog read after an unclean master shutdown.
Related errors
- status_vars_len ( ) > data_len ( )
- Query event length is too short.
- !! Don't know how to handle column type=%d meta=%d (%04X)
- !! Unknown Bit len =
- !! Unknown ENUM packlen =
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/7cbf31a6312720d3.
Report an issue: GitHub.