apache/beam · error · RuntimeError

Bundle is not in a finalizable state for

Error message

Bundle is not in a finalizable state for %s

What it means

SdkWorkerBundle finalization requires the bundle to be in a state where it can be finalized. If bundle_processor_cache.lookup returns None/raises or the processor for instruction_id is not in a finalizable state, RuntimeError 'Bundle is not in a finalizable state' is raised. Beam notes this happens when finalize arrives while the bundle is still initializing or after it was already finalized and released.

Solutions

  1. Ensure the runner sends finalize exactly once per successful process_bundle.
  2. Fix runner-side retries to use a new instruction id rather than re-finalizing a completed one.
  3. Align runner and SDK harness versions so lifecycle state transitions match.
  4. If caused by concurrent control messages, serialize finalize handling on the runner or upgrade Beam to a version with the relevant race fixed.

Example fix

# before
await send(ProcessBundle(instruction_id=i))
await send(FinalizeBundle(instruction_id=i))
await send(FinalizeBundle(instruction_id=i))  # retry duplicates finalize

# after
await send(ProcessBundle(instruction_id=i))
if not finalized_ids.add(i):
    await send(FinalizeBundle(instruction_id=i))  # finalize only once
Defensive patterns

Strategy: validation

Validate before calling

if instruction_id in finalized_instruction_ids:
    raise ValueError(f'{instruction_id} already finalized; finalize must be sent once')

Try / catch

try:
    finalize_bundle(request)
except RuntimeError as e:
    if 'not in a finalizable state' in str(e):
        log.warning('duplicate/late finalize for %s', request.instruction_id)
        return  # treat as idempotent no-op if the bundle already completed
    raise

Prevention

When it happens

Trigger: A finalize_bundle(request) arrives for an instruction id whose BundleProcessor was already finalized and released, or is still being set up, or was discarded due to failure.

Common situations: Runner retry logic sending finalize twice for one bundle; race between bundle completion and finalize control messages; runner/harness version skew in the bundle lifecycle protocol; very short-lived bundles where finalize is delayed past release.

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/d554a85d1ee25e4d. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/runners/worker/sdk_worker.py:802

    # type: (...) -> beam_fn_api_pb2.InstructionResponse
    try:
      processor = self.bundle_processor_cache.lookup(request.instruction_id)
    except RuntimeError:
      return beam_fn_api_pb2.InstructionResponse(
          instruction_id=instruction_id, error=traceback.format_exc())
    if processor:
      try:
        finalize_response = processor.finalize_bundle()
        self.bundle_processor_cache.release(request.instruction_id)
        return beam_fn_api_pb2.InstructionResponse(
            instruction_id=instruction_id, finalize_bundle=finalize_response)
      except Exception as e:
        self.bundle_processor_cache.discard(request.instruction_id, e)
        raise
    # We can reach this state if there was an erroneous request to finalize
    # the bundle while it is being initialized or has already been finalized
    # and released.
    raise RuntimeError(
        'Bundle is not in a finalizable state for %s' % instruction_id)

  @contextlib.contextmanager
  def maybe_profile(self, instruction_id):
    # type: (str) -> Iterator[None]
    if self.profiler_factory:
      profiler = self.profiler_factory(instruction_id)
      if profiler:
        with profiler:
          yield
      else:
        yield
    else:
      yield


class StateHandler(metaclass=abc.ABCMeta):
  """An abstract object representing a ``StateHandler``."""

View on GitHub (pinned to 12126d8942)