langchain-ai/deepagents · error · RuntimeError

Context Hub mutation deadline is missing

Error message

Context Hub mutation deadline is missing

What it means

`_take_batch` waits on the mutation queue's condition until the queue's deadline expires, then drains `queue.pending`. If pending mutations exist but `queue.deadline` is `None`, the batching invariant is broken (a deadline must always be set when mutations are enqueued), so it raises `RuntimeError` instead of waiting forever.

Source

Thrown at libs/deepagents/deepagents/backends/context_hub.py:239

    @staticmethod
    def _wait_for_mutation(mutation: _Mutation) -> None:
        mutation.done.wait()
        if mutation.error is not None:
            raise mutation.error

    def _submit_changes(self, changes: dict[str, str | None]) -> None:
        with self._mutations.condition:
            self._ensure_cache_locked()
            mutation = self._queue_changes_locked(changes)
        self._wait_for_mutation(mutation)

    def _take_batch(self) -> list[_Mutation] | None:
        queue = self._mutations
        with queue.condition:
            while queue.pending:
                if queue.deadline is None:
                    msg = "Context Hub mutation deadline is missing"
                    raise RuntimeError(msg)
                remaining = queue.deadline - time.monotonic()
                if remaining > 0:
                    queue.condition.wait(timeout=remaining)
                    continue
                batch = queue.pending
                queue.pending = []
                queue.deadline = None
                queue.in_flight = batch
                return batch
            self._worker = None
            return None

    @staticmethod
    def _merge_batch(batch: list[_Mutation]) -> dict[str, str | None]:
        changes: dict[str, str | None] = {}
        for mutation in batch:
            changes.update(mutation.changes)
        return changes

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Upgrade/align library versions so enqueue always sets a deadline before appending pending mutations.
  2. Avoid touching the internal `_mutations` queue directly; use the public submit APIs that schedule the deadline.
  3. Report/reproduce as a concurrency bug if it occurs on stock APIs — the fix belongs in enqueue ordering.

Example fix

// before (incorrect internal enqueue)
queue.pending.append(mutation)  # deadline never set
// after
queue.deadline = time.monotonic() + BATCH_WINDOW
queue.pending.append(mutation)
queue.condition.notify_all()
Defensive patterns

Strategy: try-catch

Try / catch

try:
    backend.submit_changes(changes)
except RuntimeError as e:
    if "mutation deadline is missing" in str(e):
        recreate_backend_and_resubmit(changes)  # internal invariant violated; rebuild state
    else:
        raise

Prevention

When it happens

Trigger: The mutation-draining loop (`_drain_mutations` → `_take_batch`) encounters a queue with pending entries whose deadline was never set — a bug in enqueue ordering or a queue constructed/mutated outside the expected `deadline`-setting path.

Common situations: Concurrent enqueue racing with drain such that pending is visible before the deadline is assigned; custom code poking at internal `_mutations` queue; library-version mismatch where one component sets pending without a deadline.

Related errors


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