apache/seatunnel · error · IllegalStateException
The split fetcher manager has closed.
Error message
The split fetcher manager has closed.
What it means
SplitFetcherManager.createSplitFetcher() is guarded against use after the manager has been closed. When closed==true it throws this IllegalStateException instead of creating a fetcher whose executor no longer exists, keeping shutdown state consistent.
Source
Thrown at seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/reader/fetcher/SplitFetcherManager.java:98
// Add the exception to the exception list.
uncaughtFetcherException.get().addSuppressed(throwable);
}
};
String taskThreadName = Thread.currentThread().getName();
this.executors =
Executors.newCachedThreadPool(
r -> new Thread(r, "Source Data Fetcher for " + taskThreadName));
}
public abstract void addSplits(Collection<SplitT> splitsToAdd);
protected void startFetcher(SplitFetcher<E, SplitT> fetcher) {
executors.submit(fetcher);
}
protected synchronized SplitFetcher<E, SplitT> createSplitFetcher() {
if (closed) {
throw new IllegalStateException("The split fetcher manager has closed.");
}
// Create SplitReader.
SplitReader<E, SplitT> splitReader = splitReaderFactory.get();
int fetcherId = fetcherIdGenerator.getAndIncrement();
SplitFetcher<E, SplitT> splitFetcher =
new SplitFetcher<>(
fetcherId,
elementsQueue,
splitReader,
errorHandler,
() -> {
fetchers.remove(fetcherId);
},
this.splitFinishedHook);
fetchers.put(fetcherId, splitFetcher);
return splitFetcher;
}
View on GitHub (pinned to cf67b549a7)
Solutions
- Check job lifecycle: ensure addSplits isn't called after close — this is usually a race, so check shutdown ordering logs
- Retry-safe pattern: catch IllegalStateException and drop splits if the reader is intentionally closed
- Fix the race by synchronizing split assignment against reader shutdown in the enumerator/reader glue
- Upgrade SeaTunnel if a known race between close() and addSplits() is the trigger
Example fix
// before
splitFetcherManager.addSplits(splits); // may throw after close
// after
if (!splitFetcherManager.isClosed()) { // guard via manager state where exposed
splitFetcherManager.addSplits(splits);
} Defensive patterns
Strategy: validation
Validate before calling
// guard against adding splits after close
if (splitFetcherManager.isClosed()) { // expose/query closed state if available
LOG.warn("split fetcher manager closed; dropping {} splits", splits.size());
return;
}
splitFetcherManager.addSplits(splits); Type guard
boolean canAcceptSplits(SplitFetcherManager<?, ?> m) {
try {
java.lang.reflect.Field f = m.getClass().getDeclaredField("closed");
f.setAccessible(true);
return !f.getBoolean(m);
} catch (ReflectiveOperationException e) {
return false;
}
} Try / catch
try {
splitFetcherManager.addSplits(splits);
} catch (IllegalStateException e) {
if (e.getMessage().contains("split fetcher manager has closed")) {
LOG.warn("manager closed during split assignment; ignoring", e);
return;
}
throw e;
} Prevention
- Synchronize split assignment against source reader close() in enumerator/reader glue
- Don't close the source reader while splits may still be assigned
- Check shutdown ordering in custom SourceReader implementations
- Treat this error as a lifecycle race signal; log job phase around close/addSplits
When it happens
Trigger: Calling addSplits (or any path that lazily creates a fetcher) after SplitFetcherManager.close() has run — e.g. splits arriving while the reader is being closed, or a race between SplitEnumerator assigning splits and source reader closure.
Common situations: Job cancel/fail concurrently with split assignment; checkpoint recovery ordering where a stale reader receives splits; user code closing the source reader then adding splits.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- BigtableSourceSplitEnumerator already closed; cannot create
- BigtableSourceSplitEnumerator closed during client creation
- BUFFER_ADD_FAILED
- Python source was closed while writing python.script.config
- Error sink is closing for stage [%s], plugin [%s]
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/3780e1f5377df0f6.
Report an issue: GitHub.