langchain-ai/deepagents · error · RuntimeError

task call limiter not initialized

Error message

task call limiter not initialized

What it means

The task bridge raises this RuntimeError when `_task_calls` (the asyncio.Semaphore limiting concurrent subagent dispatches per REPL thread) is None even though an eval is active. The semaphore is allocated in `_ainit` only when `subagents_enabled` is true; its absence means the task bridge was registered without the limiter ever being created — an inconsistent internal state.

Source

Thrown at libs/partners/quickjs/langchain_quickjs/_repl.py:628

        try:
            return await asyncio.wrap_future(future)
        except asyncio.CancelledError:
            future.cancel()
            raise

    def _register_task_bridge(self) -> None:
        """Install the async host function backing top-level `task()`."""
        ctx = self._require_ctx()

        async def _bridge(raw_input: Any = None) -> Any:
            state = self._ptc_state
            if state is None:
                msg = "task bridge called outside active eval"
                raise ConcurrentEvalError(msg)
            task_calls = self._task_calls
            if task_calls is None:
                msg = "task call limiter not initialized"
                raise RuntimeError(msg)

            payload = _normalize_tool_input(raw_input)
            async with task_calls:
                try:
                    result = await self._ainvoke_task_on_outer_loop(
                        payload,
                        state=state,
                    )
                except GraphInterrupt:
                    raise
                except Exception as e:
                    # Subagent dispatches are part of the eval language, not
                    # PTC calls. Surface their validation/runtime failures as
                    # eval errors without changing normal `tools.*` semantics.
                    raise _TaskBridgeError(e) from e
            return coerce_tool_output_for_ptc(result)

        ctx.register(_TASK_FUNCTION_NAME, _bridge, is_async=True)

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Report/fix the initialization ordering so `_task_calls` is allocated whenever the task bridge is registered
  2. Recreate the REPL to get a consistent `_ainit`
  3. Ensure nothing resets `_task_calls` to None while evals can run
Defensive patterns

Strategy: try-catch

Validate before calling

# Python side sanity check after constructing the REPL
if repl._subagents_enabled:
    assert repl._task_calls is not None, 'task limiter missing after init'

Try / catch

try:
    result = await task(payload)
except (RuntimeError,) as e:
    if 'limiter not initialized' in str(e):
        raise InconsistentReplState('recreate the REPL') from e
    raise

Prevention

When it happens

Trigger: An active eval's bridge finds `self._task_calls is None` — e.g. `_register_task_bridge` ran but `_ainit` never allocated the semaphore (subagent flag changed after init), or init was partially executed/failed midway.

Common situations: Custom subclass or patching that registers the task bridge without enabling subagents, exceptions during `_ainit` after bridge registration, or concurrency bugs where state was cleared/reset mid-eval.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/10474a7c5283efce. Report an issue: GitHub.