{"record":{"id":"73ef931168118c60","repo":"langchain-ai/deepagents","slug":"quickjs-context-is-closed","errorCode":null,"errorMessage":"QuickJS context is closed","messagePattern":"QuickJS context is closed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/partners/quickjs/langchain_quickjs/_repl.py","lineNumber":450,"sourceCode":"        self._task_calls: asyncio.Semaphore | None = None\n        # Context creation + console install must happen on the worker\n        # thread. Block caller here so the REPL is ready to use when\n        # __init__ returns.\n        worker.run_sync(self._ainit())\n\n    async def _ainit(self) -> None:\n        self._ctx = self._runtime.new_context(timeout=self._per_call_timeout)\n        if self._capture_console:\n            self._install_console()\n        if self._subagents_enabled:\n            self._task_calls = asyncio.Semaphore(_MAX_TASK_CALLS_PER_THREAD)\n            self._register_task_bridge()\n\n    def _require_ctx(self) -> Context:\n        \"\"\"Return the live QuickJS context or raise if this REPL is closed.\"\"\"\n        if self._ctx is None:\n            msg = \"QuickJS context is closed\"\n            raise RuntimeError(msg)\n        return self._ctx\n\n    def _install_console(self) -> None:\n        ctx = self._require_ctx()\n        buf = self._console\n\n        @ctx.function(name=\"__console_log\")\n        def _log(*args: Any) -> None:\n            buf.append(\"log\", args)\n\n        @ctx.function(name=\"__console_warn\")\n        def _warn(*args: Any) -> None:\n            buf.append(\"warn\", args)\n\n        @ctx.function(name=\"__console_error\")\n        def _error(*args: Any) -> None:\n            buf.append(\"error\", args)\n","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/partners/quickjs/langchain_quickjs/_repl.py#L432-L468","documentation":"The QuickJS REPL raises this RuntimeError from `_require_ctx` when its internal `Context` handle is None, i.e. the REPL has been closed and its JS context released. Any lifecycle method (installing console/tools, registering the task bridge, snapshot/restore) that needs a live context checks this first and refuses to operate on a dead REPL. It protects against use-after-free of the underlying QuickJS VM.","triggerScenarios":"Calling any REPL method after `close()`/aclose was called, or after the context was torn down: `install_tools`, `_install_console`, `_register_task_bridge`, `_register_tool_bridge`, or `_acreate_snapshot`/`_arestore_snapshot`.","commonSituations":"Using the REPL after an async context-exit (`async with` block ended), reusing a cached REPL object that another code path closed, or a shutdown race where a background task tries to install tools during teardown.","solutions":["Create a fresh REPL instance instead of reusing the closed one","Audit the code path so `install_tools`/snapshot calls only happen inside the REPL's lifetime (inside the `async with` block)","Check `repl._ctx is not None` (or a public is_closed accessor) before calling lifecycle methods"],"exampleFix":"// before\nrepl.install_tools(tools)  # after repl.close() -> RuntimeError\n// after\nif not repl.is_closed:\n    repl.install_tools(tools)","handlingStrategy":"try-catch","validationCode":"if repl is None or getattr(repl, '_ctx', None) is None:\n    repl = MyQuickJSRepl(...)  # recreate before use","typeGuard":"def repl_is_live(repl) -> bool:\n    return getattr(repl, '_ctx', None) is not None","tryCatchPattern":"try:\n    repl.install_tools(tools)\nexcept RuntimeError as e:\n    if 'context is closed' in str(e):\n        repl = recreate_repl(); repl.install_tools(tools)\n    else:\n        raise","preventionTips":["Keep all REPL usage inside its async context manager lifetime","Never cache REPL objects beyond the eval that created them","Add an is_closed guard helper before lifecycle calls"],"tags":["lifecycle","quickjs","use-after-close"],"backgroundTag":"use-after-close","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}