#9959·npm

npx -y hangs on Windows when stdin is a pipe (deadlock with MCP/LSP stdio IPC)

Author: Gaoang-623Created Sep 9, 2026Updated Sep 15, 2026
LabelsPriority 2

Summary

npx -y <package> hangs indefinitely on Windows when stdin is redirected to a pipe, despite the -y flag being present. This occurs because npx still attempts to read from stdin for interactive prompts, causing a deadlock when the parent process has already taken over stdin for IPC communication.

Environment

  • OS: Windows 11
  • Node.js: v20.x / v22.x (tested on both)
  • npm: 10.x
  • Context: MCP (Model Context Protocol) stdio-based server communication

Steps to Reproduce

  1. Create a test script that spawns npx with piped stdio:
javascript
// test-npx-pipe.mjs
import { spawn } from 'child_process';

const proc = spawn('cmd', ['/c', 'npx', '-y', '@playwright/mcp'], {
  stdio: ['pipe', 'pipe', 'pipe']
});

// Send data to stdin (simulating IPC communication)
proc.stdin.write(JSON.stringify({
  jsonrpc: '2.0',
  id: 1,
  method: 'initialize',
  params: { protocolVersion: '2024-11-05', capabilities: {} }
}) + '\n');

proc.stdout.on('data', (data) => {
  console.log('Received:', data.toString());
  proc.kill();
});

proc.stderr.on('data', (data) => {
  console.error('Error:', data.toString());
});

setTimeout(() => {
  console.error('TIMEOUT: npx hung for 30 seconds');
  proc.kill();
  process.exit(1);
}, 30000);
  1. Run: node test-npx-pipe.mjs

Expected Behavior

With the -y flag, npx should:

  • Skip all interactive prompts
  • Detect that stdin is not a TTY
  • Immediately execute the package without waiting for user input

Actual Behavior

  • npx hangs indefinitely waiting for stdin input
  • The process never starts executing the target package
  • No error message is shown
  • The -y flag appears to be ignored in pipe contexts

Root Cause Analysis

When stdin is a pipe (not a TTY):

  1. npx checks if the package needs installation/verification
  2. Even with -y, npx prompts: Need to install @playwright/mcp. Ok to proceed? (y)
  3. npx tries to read from stdin
  4. Deadlock: the parent process has already reserved stdin for IPC, so npx waits forever

On Unix systems, pipe EOF behavior is more explicit, allowing npx to detect non-interactive contexts. On Windows, pipe semantics differ, and -y doesn't reliably bypass prompts in this scenario.

Workaround

Direct node execution bypasses the issue:

json
{
  "command": "C:\\Program Files\\nodejs\\node.exe",
  "args": [
    "C:\\Users\\<user>\\AppData\\Roaming\\npm\\node_modules\\@playwright\\mcp\\cli.js"
  ]
}

Impact

This affects any Windows application using stdio pipes for IPC that tries to launch npm packages via npx, including:

  • MCP (Model Context Protocol) servers
  • Language servers (LSP)
  • Any parent-child process communication using stdin/stdout

Proposed Solutions

Option 1: Auto-detect pipe mode

Skip all prompts when stdin is not a TTY and -y is present.

Option 2: Improve -y flag reliability

Make -y unconditionally skip prompts regardless of stdin state, matching user expectations.

Option 3: Better error message

If npx detects stdin is a pipe and interaction is required, fail fast with a clear error instead of hanging:

npx: cannot prompt for input (stdin is not interactive)
Use -y to skip prompts, or install globally: npm install -g <package>

Additional Context

This issue particularly affects the MCP ecosystem where:

  • All communication happens over stdio pipes (JSON-RPC protocol)
  • Community documentation recommends npx -y <package> configuration
  • Works fine on macOS/Linux, fails silently on Windows
  • Users experience "server initialization timeout" with no clear cause

The problem is intermittent because:

  • Cached packages may hit a fast path and avoid prompts
  • First-time installations always trigger the hang
  • Clearing npm cache (npm cache clean --force) makes it 100% reproducible