apache/beam · error · RuntimeError

Entry was released.

Error message

Entry was released.

What it means

In apache_beam.utils.multi_process_shared, a SingletonProxy wraps a shared object and tracks validity; singletonProxy_release() invalidates the proxy when the shared entry is released. Any subsequent call through the proxy (e.g. calling the shared object) raises RuntimeError('Entry was released.') because the underlying shared object is no longer available in this process.

Source

Thrown at sdks/python/apache_beam/utils/multi_process_shared.py:79

multiprocessing.managers.AutoProxy = patched_autoproxy  # type: ignore[attr-defined]

T = TypeVar('T')
AUTH_KEY = b'mps'


class _SingletonProxy:
  """Proxies the shared object so we can release it with better errors and no
  risk of dangling references in the multiprocessing manager infrastructure.
  """
  def __init__(self, entry):
    # Guard names so as to not conflict with names of underlying object.
    self._SingletonProxy_entry = entry
    self._SingletonProxy_valid = True

  # Used to make the shared object callable (see _AutoProxyWrapper below)
  def singletonProxy_call__(self, *args, **kwargs):
    if not self._SingletonProxy_valid:
      raise RuntimeError('Entry was released.')
    return self._SingletonProxy_entry.obj.__call__(*args, **kwargs)

  def singletonProxy_release(self):
    assert self._SingletonProxy_valid
    self._SingletonProxy_valid = False

  def singletonProxy_unsafe_hard_delete(self):
    assert self._SingletonProxy_valid
    self._SingletonProxy_entry.unsafe_hard_delete()

  def __getattr__(self, name):
    if not self._SingletonProxy_valid:
      raise RuntimeError('Entry was released.')
    try:
      return getattr(self._SingletonProxy_entry.obj, name)
    except AttributeError as e:
      # Swallow AttributeError exceptions so that they are ignored when
      # calculating public functions. These can occur if __getattr__ is

View on GitHub (pinned to 12126d8942)

Solutions

  1. Re-acquire the shared entry via MultiProcessShared/SharedAcquirer before calling it again instead of reusing a stale proxy.
  2. Keep all uses of the shared object inside the scope where the entry is acquired (e.g. the with-block).
  3. Check the proxy's validity (or track singletonProxy_release) before invoking, and re-initialize on RuntimeError.
  4. Fix thread lifecycle so release happens only after all callers are done with the proxy.

Example fix

# before
shared = multi_process_shared.MultiProcessShared(MyClass).enter()
obj = shared.acquire()
shared.exit()  # releases entry
obj()  # RuntimeError: Entry was released.

// after
shared = multi_process_shared.MultiProcessShared(MyClass).enter()
obj = shared.acquire()
try:
    obj()  # safe: entry still held
finally:
    shared.exit()
Defensive patterns

Strategy: try-catch

Validate before calling

# acquire-and-use within the same scope; check validity before use
shared = multi_process_shared.MultiProcessShared(MyClass).enter()
obj = shared.acquire()
if obj is None:
    raise RuntimeError('shared entry not acquired')

Type guard

def proxy_is_valid(proxy) -> bool:
    return getattr(proxy, '_SingletonProxy_valid', True)

Try / catch

try:
    result = shared_obj()
except RuntimeError as e:
    if 'Entry was released.' in str(e):
        shared_obj = reinitialize_shared()  # re-acquire the entry
        result = shared_obj()
    else:
        raise

Prevention

When it happens

Trigger: Holding a reference obtained via multi_process_shared.SharedAcquirer/MultiProcessShared, then calling it after the entry was released (release() called, or the shared handle's context/with-block exited) from another thread or retained closure.

Common situations: Using the shared object after leaving `with multi_process_shared.MultiProcessShared(...) as ...` scope; sharing a callable across threads where one thread releases while another still calls; caching the proxy beyond its intended lifetime in DirectRunner multiprocess modes.

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/a8d4d2ca10022d7f. Report an issue: GitHub.