langchain-ai/deepagents · error · ExtensionError

Extension factory in {source.path} attempted to exit: {exc}

Error message

Extension factory in {source.path} attempted to exit: {exc}

What it means

Raised by `load_extension` when the extension factory calls `sys.exit()` (or otherwise raises `SystemExit`) during loading. The loader treats a factory attempting to terminate the host process as a defect and converts it into an `ExtensionError` chained from the original exception.

Source

Thrown at libs/code/deepagents_code/extensions/loader.py:109

    snapshot = registry._snapshot()
    api = ExtensionAPI(registry, source, cwd=cwd, mode=mode)
    try:
        await factory(api)
    except (KeyboardInterrupt, asyncio.CancelledError):
        registry._rollback(snapshot)
        api._deactivate()
        sys.modules.pop(name, None)
        raise
    except (SystemExit, Exception) as exc:
        registry._rollback(snapshot)
        api._deactivate()
        sys.modules.pop(name, None)
        msg = (
            f"Extension factory in {source.path} attempted to exit: {exc}"
            if isinstance(exc, SystemExit)
            else f"Extension factory in {source.path} failed: {exc}"
        )
        raise ExtensionError(msg) from exc
    return api

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Remove any `sys.exit()`/`SystemExit` from the factory; raise a normal `Exception` instead
  2. Replace eager `argparse.parse_args()` calls in the factory with lazy parsing at command-invocation time
  3. On missing dependencies, raise `ImportError`/return an error rather than exiting

Example fix

// before
async def extension(api):
    if not shutil.which("rg"):
        sys.exit("ripgrep is required")

// after
async def extension(api):
    if not shutil.which("rg"):
        raise RuntimeError("ripgrep is required for the search extension")
Defensive patterns

Strategy: try-catch

Validate before calling

import ast, sys
for node in ast.walk(ast.parse(open(path).read())):
    if isinstance(node, ast.Call) and getattr(node.func, 'attr', '') == 'exit':
        raise SystemExit(f"{path} calls sys.exit inside factory")

Try / catch

try:
    api = await load_extension(source, registry)
except ExtensionError as exc:
    logger.error("extension tried to exit: %s", exc)  # original cause in exc.__cause__

Prevention

When it happens

Trigger: A factory body calls `sys.exit(1)`, `raise SystemExit`, `argparse`'s `parse_args()` exits on bad args, or `click`/`typer` CLI helpers that call `sys.exit` are invoked at import/factory time.

Common situations: Extensions reusing CLI argument-parsing code during initialization; defensive `sys.exit` on missing optional deps written for standalone scripts; copy-pasted script boilerplate inside the factory.

Related errors


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