apache/beam · error · NoSuchElementException
The current element is unavailable because either the…
Error message
The current element is unavailable because either the reader is at the beginning of the input and start() or advance() wasn't called, or the last start() or advance() returned false.
What it means
SyntheticBoundedSource's BoundedReader.getCurrent() follows the Beam reader contract: the current element only exists after start() succeeds or advance() returns true. The synthetic source (used by Beam's Nexmark/performance tests to generate deterministic byte payloads) throws NoSuchElementException when getCurrent() is called before the reader is positioned on an element.
Solutions
- Call start() once after obtaining the reader, and only call getCurrent()/getCurrentTimestamp() when it returned true.
- After each advance(), check its boolean result before reading the current element.
- Handle the empty-source case: if start() returns false, treat the source as exhausted and skip reading.
Example fix
// before
BoundedSource.BoundedReader<KV<byte[], byte[]>> r = source.createReader(pipelineOptions);
KV<byte[], byte[]> kv = r.getCurrent();
// after
BoundedSource.BoundedReader<KV<byte[], byte[]>> r = source.createReader(pipelineOptions);
if (r.start()) {
KV<byte[], byte[]> kv = r.getCurrent();
} Defensive patterns
Strategy: type-guard
Type guard
boolean hasCurrent(BoundedSource.BoundedReader<?> r) { return r.start() || false; } // only true while start()/advance() returned true Try / catch
try {
KV<byte[], byte[]> kv = reader.getCurrent();
} catch (NoSuchElementException e) {
// reader not positioned or exhausted: call start()/advance() first
} Prevention
- Always follow the start()/advance() protocol before getCurrent().
- Treat start()==false as an exhausted reader, never as an error.
- Write reader-contract tests for any custom synthetic source usage.
When it happens
Trigger: Calling reader.getCurrent() immediately after createReader() without calling start(); or calling it after advance()/start() returned false (end of input). Typically only hit by custom runner code or tests driving the reader directly.
Common situations: Custom BoundedSource harnesses or unit tests that iterate readers manually and forget the start()/advance() protocol; runners that mis-handle empty synthetic sources where start() returns false immediately.
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
- Current record is unavailable because either the reader is…
- Current timestamp is unavailable because either the reader…
- Unexpected progress shape
- Unknown delay type
- Unknown distribution type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/9a8c1d24af477e1f.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/synthetic/src/main/java/org/apache/beam/sdk/io/synthetic/SyntheticBoundedSource.java:195
this.readerDelay = new ReaderDelay(source.sourceOptions);
this.currentKvPair = null;
this.splitPointFrequencyRecords = source.sourceOptions.splitPointFrequencyRecords;
}
@Override
public synchronized SyntheticBoundedSource getCurrentSource() {
return (SyntheticBoundedSource) super.getCurrentSource();
}
@Override
protected long getCurrentOffset() throws IllegalStateException {
return currentOffset;
}
@Override
public KV<byte[], byte[]> getCurrent() throws NoSuchElementException {
if (currentKvPair == null) {
throw new NoSuchElementException(
"The current element is unavailable because either the reader is "
+ "at the beginning of the input and start() or advance() wasn't called, "
+ "or the last start() or advance() returned false.");
}
return currentKvPair;
}
@Override
public boolean allowsDynamicSplitting() {
return splitPointFrequencyRecords > 0;
}
@Override
protected final boolean startImpl() throws IOException {
this.currentOffset = getCurrentSource().getStartOffset();
if (splitPointFrequencyRecords > 0) {
while (currentOffset % splitPointFrequencyRecords != 0) {
++currentOffset;View on GitHub (pinned to 12126d8942)