npm / npm/cli

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

Open
#9,959 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Priority 2
Dominant language
JavaScript
Stars
10.1k
Forks
4.7k
Avg merge
2d 2h
Merged PRs (30d)
19

Description

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:
// 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:

{
  "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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the issue's test-npx-pipe.mjs reproduction on Windows with Node.js 20 or 22, then trace the npx prompt path when stdin is piped and -y is present. Done means the @playwright/mcp process starts without waiting for input and the behavior is covered for the described piped-stdio case.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
cli, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.