apache/seatunnel · error · ClickhouseConnectorException
never happen error !
Error message
never happen error !
What it means
This ClickhouseConnectorException with SHOULD_NEVER_HAPPEN is thrown by ClickhouseValueReader.next() when the internal rowBatch field is null. It signals an internal invariant violation: the reader's batching strategy was never initialized (no prior hasNext()/read produced a batch), so there is no row batch to return. Callers must always drive the reader through hasNext() before calling next().
Source
Thrown at seatunnel-connectors-v2/connector-clickhouse/src/main/java/org/apache/seatunnel/connectors/seatunnel/clickhouse/source/ClickhouseValueReader.java:109
this.shouldUseStreamReader = shouldUseStreamReader();
}
public boolean hasNext() {
if (shouldUseStreamReader) {
if (streamValueReader == null) {
streamValueReader = new StreamValueReader();
}
return streamValueReader.hasNext();
} else if (clickhouseSourceTable.isSqlStrategyRead()) {
return sqlBatchStrategyRead();
} else {
return partBatchStrategyRead();
}
}
public List<SeaTunnelRow> next() {
if (rowBatch == null) {
throw new ClickhouseConnectorException(
ClickhouseConnectorErrorCode.SHOULD_NEVER_HAPPEN, "never happen error !");
}
return rowBatch;
}
private boolean partBatchStrategyRead() {
List<ClickhousePart> parts = clickhouseSourceSplit.getParts();
int partSize = parts.size();
if (currentPartIndex >= partSize) {
return false;
}
ClickhousePart currentPart = parts.get(currentPartIndex);
// If current part has been processed, move to the next part
if (currentPart.isEndOfPart()) {View on GitHub (pinned to cf67b549a7)
Solutions
- Always call hasNext() and only call next() when it returns true — this initializes rowBatch via partBatchStrategyRead()/sqlBatchStrategyRead()
- Check that the split was properly opened/initialized before reading (reader state set up in the split enumerator/reader lifecycle)
- If this occurs in normal SeaTunnel flow, enable debug logging on the reader and file a bug with the split/shard info since it indicates an internal state bug
- Ensure the split being read actually matched a ClickHouse part/shard so a batching strategy was selected
Example fix
// before
List<SeaTunnelRow> rows = reader.next();
// after
if (reader.hasNext()) {
List<SeaTunnelRow> rows = reader.next();
} Defensive patterns
Strategy: type-guard
Validate before calling
// Java: guard before consuming
if (!reader.hasNext()) {
throw new IllegalStateException("Reader has no batch; hasNext() must be called before next()");
} Type guard
boolean canRead(ClickhouseValueReader reader) {
try {
return reader.hasNext();
} catch (Exception e) {
return false;
}
} Try / catch
try {
rows = reader.next();
} catch (ClickhouseConnectorException e) {
if (e.getErrorCode() == ClickhouseConnectorErrorCode.SHOULD_NEVER_HAPPEN) {
// reinitialize the reader/split and retry from checkpoint
}
throw e;
} Prevention
- Only call next() after hasNext() returns true, mirroring the SeaTunnel SourceReader poll loop
- Never cache a reader across failures without re-opening/re-initializing the split
- Treat SHOULD_NEVER_HAPPEN as a bug report: capture split id and shard and report it
When it happens
Trigger: Calling next() on a ClickhouseValueReader whose rowBatch is null — i.e., next() is invoked before any successful hasNext()/batch-read call, or after the reader was constructed but never advanced, or when no batching strategy was configured.
Common situations: Custom or patched source reader code that calls next() without first calling hasNext(); a reader deserialized/reinitialized after failure where rowBatch was never populated; misuse of the reader API outside the normal SourceReader poll loop.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- No split assigned
- Failed to read data from part %s, shard: %s, splitId: %s, me
- Failed to read data from sql %s, shard: %s, splitId %s, mess
- Invalid state: currentSplitId is null when emitting records.
- Cannot fetch from another split - no split remaining.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/36c9b65cd5ba0a94.
Report an issue: GitHub.