Skip to content

[Bug]: pi install hangs indefinitely — context-mode MCP server spawned but never cleaned up #824

@chagwood

Description

@chagwood

Platform

OpenClaw (Pi Agent)

context-mode version

latest as of 2026-06-12

Debug script output (REQUIRED)

Active handles: 6
  Handle 0: Socket fd=1 (stdout)          ← normal
  Handle 1: Socket fd=2 (stderr)          ← normal
  Handle 2: Socket fd=26                  ← MCP bridge pipe
  Handle 3: Socket fd=28                  ← MCP bridge pipe
  Handle 4: Socket fd=30                  ← MCP bridge pipe
  Handle 5: ChildProcess pid=126705       ← THE CULPRIT
    args=["/usr/bin/node",".../context-mode/server.bundle.mjs"]
    closesNeeded=3

=== DETECTED: Spawning server.bundle.mjs ===
  command: /usr/bin/node
  args: /home/chagwood/.pi/agent/npm/node_modules/context-mode/server.bundle.mjs
  argv[2]: install
  isPiShortCircuitArgv would return: false

pi version: 0.79.2
OS: Linux (x86_64)
Node.js: /usr/bin/node

Exact prompt that triggered the bug (REQUIRED)

pi install npm:pi-subagents

Full error output (REQUIRED)

The command prints:

Installing npm:pi-subagents...
...
Installed npm:pi-subagents


...and then the terminal hangs indefinitely. Ctrl+C is required to exit.

Root cause: The Pi extension in build/adapters/pi/extension.js has a short-circuit guard (PI_SHORT_CIRCUIT_TOKENS) that skips spawning the MCP server for --help and --version, but install/uninstall/remove/update/list/config are NOT in the short-circuit set.

The MCP bridge spawns server.bundle.mjs as a child process with piped stdio:
  this.child = spawn(runtime, [this.serverScript], { stdio: ["pipe", "pipe", "pipe"], env: childEnv });

When pi install finishes, main() returns, but the child process is still alive with 3 open pipes. Node.js refuses to exit because there is still an active ChildProcess handle in the event loop.

The cleanup path (session_shutdown handler) calls _mcpBridge.shutdown() which sends SIGTERM — but that event only fires during interactive session shutdown, never for pi install.

process._getActiveHandles() 6 seconds after install completes:
  Handle 5: ChildProcess pid=126705
    args=["/usr/bin/node",".../context-mode/server.bundle.mjs"]
    closesNeeded=3

Steps to reproduce (REQUIRED)

  1. Run: pi install npm:pi-subagents
  2. Observe the success message is printed:
    Installing npm:pi-subagents...
    ...
    Installed npm:pi-subagents
    
  3. The terminal hangs indefinitely after the success message
  4. Ctrl+C is required to exit
  5. The process never exits on its own

The issue is reproducible with any pi install command (also uninstall, remove, update, list, config).

What have you tried to fix it?

Root cause identified: The Pi extension in build/adapters/pi/extension.js has a short-circuit guard (PI_SHORT_CIRCUIT_TOKENS) that skips spawning the MCP server for --help and --version, but package management subcommands (install, uninstall, remove, update, list, config) are NOT in the short-circuit set.

The MCP bridge spawns server.bundle.mjs via bootstrapMCPTools() as a child process with piped stdio. When pi install finishes, main() returns, but the child process is still alive with 3 open pipes. Node.js refuses to exit because there is still an active ChildProcess handle in the event loop.

The cleanup path (session_shutdown handler) calls _mcpBridge.shutdown() which sends SIGTERM — but that event only fires during interactive session shutdown, never for pi install.

Proposed fix: Add the package management subcommands to PI_SHORT_CIRCUIT_TOKENS:

// Before:
const PI_SHORT_CIRCUIT_TOKENS = new Set(["--help", "-h", "--version", "-v", "help"]);

// After:
const PI_SHORT_CIRCUIT_TOKENS = new Set([
    "--help", "-h", "--version", "-v", "help",
    "install", "uninstall", "remove", "update", "list", "config",
]);

Verification after applying fix locally:

Metric Before After
Exits? Hangs forever Clean exit
Exit code 124 (killed by timeout) 0
Time infinity ~3.5s
server.bundle.mjs spawned Yes (unnecessary) No

Related: Issue #534 fixed the same class of problem for --help/--version but missed the package management subcommands.

Pre-submission checklist

  • I have run the debug script and pasted the output above
  • I am using the latest version of context-mode
  • I have searched existing issues for duplicates
  • I have included steps to reproduce the issue

Operating System

Linux (Ubuntu/Debian)

JS Runtime

22.22.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions