apache/beam · error · IllegalStateException
Expected state to be PENDING or STARTED, but was COMPLETE_SU
Error message
Expected state to be PENDING or STARTED, but was COMPLETE_SUCCESS
What it means
RpcQosImpl's AttemptState.checkActive() verifies that a Qos attempt is still in progress before it is used. Calling checkActive() on an attempt already marked COMPLETE_SUCCESS is a lifecycle violation, so IllegalStateException is thrown. The Qos budget/scheduler relies on strict state transitions and refuses to operate on finished attempts.
Source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/firestore/RpcQosImpl.java:189
sampleUpdate.getMillis(),
1 /* numSignificantBuckets */,
1 /* numSignificantSamples */,
Sum.ofLongs());
}
private enum AttemptState {
PENDING,
STARTED,
COMPLETE_SUCCESS,
COMPLETE_ERROR;
public void checkActive() {
switch (this) {
case PENDING:
case STARTED:
return;
case COMPLETE_SUCCESS:
throw new IllegalStateException(
"Expected state to be PENDING or STARTED, but was COMPLETE_SUCCESS");
case COMPLETE_ERROR:
throw new IllegalStateException(
"Expected state to be PENDING or STARTED, but was COMPLETE_ERROR");
}
}
public void checkStarted() {
switch (this) {
case STARTED:
return;
case PENDING:
throw new IllegalStateException("Expected state to be STARTED, but was PENDING");
case COMPLETE_SUCCESS:
throw new IllegalStateException("Expected state to be STARTED, but was COMPLETE_SUCCESS");
case COMPLETE_ERROR:
throw new IllegalStateException("Expected state to be STARTED, but was COMPLETE_ERROR");
}View on GitHub (pinned to 12126d8942)
Solutions
- Do not reuse an Attempt after completeSuccessfully(); obtain a new attempt via qos.newAttempt() for each operation.
- Check the attempt lifecycle: call checkActive()/checkStarted() only before completion, at the start of each attempt.
- Guard concurrent access to the Attempt object with synchronization or restrict it to a single thread.
- Update the Beam Firestore connector if this occurs inside library code — it may be a fixed internal bug.
Example fix
// before RpcQos.Attempt attempt = qos.newAttempt(); attempt.completeSuccessfully(); attempt.checkActive(); // throws // after RpcQos.Attempt attempt = qos.newAttempt(); attempt.checkActive(); attempt.completeSuccessfully(); // check before completion only
Defensive patterns
Strategy: try-catch
Validate before calling
// Java: verify attempt is still usable before reuse
if (attemptState == RpcQosImpl.AttemptState.COMPLETE_SUCCESS) {
attempt = qos.newAttempt(); // create new attempt instead of reusing
} Type guard
boolean isUsable(RpcQos.Attempt attempt) {
try { attempt.checkActive(); return true; }
catch (IllegalStateException e) { return false; }
} Try / catch
try {
attempt.checkActive();
// proceed with RPC
} catch (IllegalStateException e) {
attempt = qos.newAttempt(); // restart lifecycle on stale attempt
} Prevention
- Never reuse an Attempt after completeSuccessfully().
- Create a new attempt per logical operation.
- Keep Attempt usage single-threaded or synchronized.
When it happens
Trigger: Reusing a completed RpcQos.Attempt object after completeSuccessfully() has been called — e.g. calling attempt.checkActive() again, or a write batch / awaitOutOfQuotaNotification flow that re-enters with the same attempt — within Firestore connector pipeline code.
Common situations: Custom DoFn or sink code holding onto a Qos Attempt across retries; concurrent threads completing and re-checking the same attempt; bugs in custom code layered on the Firestore connector internals.
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
- Expected state to be PENDING or STARTED, but was COMPLETE_ER
- Expected state to be STARTED, but was PENDING
- Expected state to be STARTED, but was COMPLETE_SUCCESS
- Error collections cannot be added after Error Handler is clo
- ErrorHandler must be finalized before the output can be retu
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/57fc1da9d28e13b5.
Report an issue: GitHub.