apache/flink · error · IOException
Cannot fetch from another split - no split remaining
Error message
Cannot fetch from another split - no split remaining
What it means
FileSourceSplitReader.checkSplitOrStartNext polls the internal split queue when the current reader is exhausted or null. If the queue is empty (splits.poll() returns null), it throws an IOException indicating there are no more splits to process. This is a control-flow signal that the reader has consumed all assigned splits.
Source
Thrown at flink-connectors/flink-connector-files/src/main/java/org/apache/flink/connector/file/src/impl/FileSourceSplitReader.java:103
@Override
public void wakeUp() {}
@Override
public void close() throws Exception {
if (currentReader != null) {
currentReader.close();
}
}
private void checkSplitOrStartNext() throws IOException {
if (currentReader != null) {
return;
}
final SplitT nextSplit = splits.poll();
if (nextSplit == null) {
throw new IOException("Cannot fetch from another split - no split remaining");
}
currentSplitId = nextSplit.splitId();
final Optional<CheckpointedPosition> position = nextSplit.getReaderPosition();
currentReader =
position.isPresent()
? readerFactory.restoreReader(config, nextSplit)
: readerFactory.createReader(config, nextSplit);
}
private FileRecords<T> finishSplit() throws IOException {
if (currentReader != null) {
currentReader.close();
currentReader = null;
}
final FileRecords<T> finishRecords = FileRecords.finishedSplit(currentSplitId);View on GitHub (pinned to 2f3c205e92)
Solutions
- Ensure the enumerator assigns splits or signals no-more-splits before the reader exhausts its queue. Check that the enumerator's handleSplitRequest properly assigns splits.
- In custom reader wrappers, check for available splits before calling fetch(); propagate the no-more-splits signal correctly.
- In tests, ensure splits are added to the reader via addSplits before calling fetch().
Example fix
// before // reader.fetch() called with no splits in queue // after reader.addSplits(Collections.singletonList(split)); // then call fetch() // or check if reader has finished all splits before calling fetch()
Defensive patterns
Strategy: validation
Validate before calling
// Before calling fetch(), verify the reader has splits or a current reader
// This is framework-managed; in custom wrappers, track split availability:
if (reader.getCurrentSplitId() == null && !reader.hasSplitsAvailable()) {
// do not call fetch(); signal completion instead
return;
} Try / catch
try {
return reader.fetch();
} catch (IOException e) {
if (e.getMessage().contains("no split remaining")) {
// No more splits to process; signal completion
return null; // or appropriate empty records
}
throw e;
} Prevention
- In custom reader wrappers, track whether splits remain before calling fetch().
- Ensure the enumerator assigns splits before the reader is polled.
- In tests, always add splits via addSplits() before calling fetch().
When it happens
Trigger: fetch() is called after all assigned splits have been consumed (currentReader is null and splits queue is empty). This can happen if the source reader is polled after it has finished all work but before the enumerator has signaled no-more-splits, or in a custom integration that calls fetch() without first providing splits.
Common situations: Reader polled after all splits processed but framework has not yet terminated the task. Custom source reader wrapper calling fetch() without ensuring splits are available. Race condition in testing where the reader is exercised before splits are assigned.
Related errors
- The SplitChange type of %s is not supported.
- Failed to create enumerator for sourceIndex={currentSourceIn
- Invalid version %d
- Invalid option %s. Must be a positive integer.
- ${message}
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/fd6af4f18fb5c34a.
Report an issue: GitHub.