apache/beam · info · PoisonedException
PoisonedException
Error message
PoisonedException
What it means
While inserting a placeholder future in forwardToConsumerForInstructionId, the computeIfAbsent callback detects the instruction id was poisoned and throws PoisonedException (a sentinel exception). onNext uses this to discard inbound data for an instruction that previously failed, treating it as ignorable rather than a data-plane error.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/fn/data/BeamFnDataGrpcMultiplexer.java:274
}
for (BeamFnApi.Elements.Timers timers : value.getTimersList()) {
if (instructionId.equals(timers.getInstructionId())) {
builder.addTimers(timers);
}
}
forwardToConsumerForInstructionId(instructionId, builder.build());
}
}
private void forwardToConsumerForInstructionId(String instructionId, BeamFnApi.Elements value) {
CloseableFnDataReceiver<BeamFnApi.Elements> consumer;
try {
CompletableFuture<CloseableFnDataReceiver<BeamFnApi.Elements>> consumerFuture =
receivers.computeIfAbsent(
instructionId,
(unused) -> {
if (poisonedInstructionIds.getIfPresent(instructionId) != null) {
throw new PoisonedException();
}
LOG.debug(
"Received data for instruction {} without consumer ready. "
+ "Waiting for consumer to be registered.",
instructionId);
return new CompletableFuture<>();
});
// The consumer may not be registered until the bundle processor is fully constructed so we
// conservatively set
// a high timeout. Poisoning will prevent this for occurring for consumers that will not be
// registered.
consumer = consumerFuture.get(3, TimeUnit.HOURS);
/*
* TODO: On failure we should fail any bundles that were impacted eagerly
* instead of relying on the Runner harness to do all the failure handling.
*/
} catch (TimeoutException e) {
LOG.error(View on GitHub (pinned to 12126d8942)
Solutions
- No user action usually needed: PoisonedException is caught internally and the data is ignored by design.
- If seen repeatedly, check for SDK/runner version mismatches causing bundles to be failed while data is still in flight.
- Ensure process-bundle failures are communicated promptly (fail bundle) so the harness stops streaming data for that instruction.
Defensive patterns
Strategy: try-catch
Try / catch
try { multiplexer.onNext(elements); } catch (PoisonedException e) { /* expected: ignore data for failed instruction */ } Prevention
- Fail bundles promptly so the harness stops streaming
- Keep harness and runner versions aligned
- Treat data after poisoning as ignorable by contract
When it happens
Trigger: gRPC inbound onNext delivers BeamFnApi.Elements for an instruction id that was poisoned via poison(instructionId) after a processing failure, and no receiver future exists for it.
Common situations: SDK harness sends trailing/last elements for a bundle the runner already failed; network-level retries redeliver data for an aborted instruction.
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
- Instruction id was poisoned
- Unregistering consumer which was not registered.
- UnsupportedOperationException
- NoSuchElementException
- Unable to find inbound data receiver for instruction %s and
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/d2f7a439804c810a.
Report an issue: GitHub.