Heuristic:MarketSquare Robotframework browser Windows Shell NPM Workaround
| Knowledge Sources | |
|---|---|
| Domains | Troubleshooting, Platform_Compatibility |
| Last Updated | 2026-02-12 04:00 GMT |
Overview
Platform-specific workaround that enables `shell=True` for subprocess calls on Windows because npm is not found in PATH without shell resolution.
Description
On Windows, the `npm` command is implemented as a `.cmd` batch script (`npm.cmd`) rather than a native executable. Python's `subprocess.Popen` and `subprocess.run` cannot find `.cmd` files when `shell=False` (the default). The library detects the Windows platform and sets `shell=True` for npm-related subprocess calls. However, `shell=True` breaks the Linux CI environment, so it is conditionally enabled only on Windows.
Usage
This heuristic is relevant when debugging npm command failures on Windows or when adding new subprocess calls that invoke npm. If npm commands fail with `FileNotFoundError` on Windows, the missing `shell=True` flag is the likely cause.
The Insight (Rule of Thumb)
- Action: Set `shell=True` for npm-related subprocess calls on Windows; keep `shell=False` on Linux and macOS.
- Value: `SHELL = bool(IS_WINDOWS)` where `IS_WINDOWS = platform.system() == "Windows"`.
- Trade-off: `shell=True` on Windows introduces a minor security risk (shell injection) but is necessary for npm PATH resolution. Using `shell=True` on Linux breaks CI.
Reasoning
Windows handles command resolution differently from Unix. On Unix, `npm` is a shell script with a shebang (`#!/usr/bin/env node`) that the kernel can execute directly. On Windows, `npm.cmd` is a batch script that requires the Windows command processor (`cmd.exe`) to execute. Python's `subprocess` module does not resolve `.cmd` extensions by default. The comment in the source code explicitly states: "This is required because weirdly windows doesn't have `npm` in PATH without shell=True. But shell=True breaks our linux CI."
Code Evidence
From `Browser/entry/constant.py:25-28`:
IS_WINDOWS = platform.system() == "Windows"
# This is required because weirdly windows doesn't have `npm` in PATH without shell=True.
# But shell=True breaks our linux CI
SHELL = bool(IS_WINDOWS)