fix(dev): pass --inspect as CLI flag, not via NODE_OPTIONS
NODE_OPTIONS is inherited by every grandchild node process. With --inspect in there, every vitest worker, agent subprocess, and claude invocation the dashboard spawned tried to bind 127.0.0.1:9229 and emitted "address already in use" — those failure strings ended up in agent logs (visible in heap diagnostics). Pass inspector flags directly on the node command line so they apply only to the dashboard process. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,8 +18,10 @@ const rawArgs = process.argv.slice(2);
|
|||||||
|
|
||||||
// --inspect / --inspect-brk / --inspect=PORT enables the Node inspector and
|
// --inspect / --inspect-brk / --inspect=PORT enables the Node inspector and
|
||||||
// auto-dumps a heap snapshot just before the heap limit is hit. Strip these
|
// auto-dumps a heap snapshot just before the heap limit is hit. Strip these
|
||||||
// from forwarded args so they don't reach the dashboard CLI parser; they go
|
// from forwarded args so they don't reach the dashboard CLI parser. We pass
|
||||||
// into NODE_OPTIONS instead so tsx's child node process picks them up.
|
// them as CLI flags directly to node (NOT via NODE_OPTIONS), because
|
||||||
|
// NODE_OPTIONS is inherited by every grandchild process — every vitest /
|
||||||
|
// agent / claude subprocess would then try to bind 9229 and fail.
|
||||||
const inspectFlags = [];
|
const inspectFlags = [];
|
||||||
const args = [];
|
const args = [];
|
||||||
for (const a of rawArgs) {
|
for (const a of rawArgs) {
|
||||||
@@ -33,15 +35,13 @@ if (inspectFlags.length > 0) {
|
|||||||
// 3 = take up to 3 snapshots as we approach the heap limit. Files land in
|
// 3 = take up to 3 snapshots as we approach the heap limit. Files land in
|
||||||
// CWD as Heap.YYYYMMDD.HHMMSS.PID.NNN.heapsnapshot
|
// CWD as Heap.YYYYMMDD.HHMMSS.PID.NNN.heapsnapshot
|
||||||
inspectFlags.push("--heapsnapshot-near-heap-limit=3");
|
inspectFlags.push("--heapsnapshot-near-heap-limit=3");
|
||||||
console.log(`[dev-with-memory] inspector enabled: ${inspectFlags.join(" ")}`);
|
console.log(`[dev-with-memory] inspector flags: ${inspectFlags.join(" ")}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base NODE_OPTIONS applied to every spawned node process (build + run).
|
// NODE_OPTIONS is shared with every spawned node process (build + run +
|
||||||
// Inspector flags are NOT here — they go only on the final tsx run, otherwise
|
// agents). Heap size belongs here. Inspector flags do NOT — see comment above.
|
||||||
// `pnpm build` would grab port 9229 first and tsx would fail to bind.
|
const nodeOptions = `--max-old-space-size=${MEMORY_MB} ${process.env.NODE_OPTIONS || ""}`.trim();
|
||||||
const baseNodeOptions = `--max-old-space-size=${MEMORY_MB} ${process.env.NODE_OPTIONS || ""}`.trim();
|
process.env.NODE_OPTIONS = nodeOptions;
|
||||||
process.env.NODE_OPTIONS = baseNodeOptions;
|
|
||||||
const runNodeOptions = `${baseNodeOptions} ${inspectFlags.join(" ")}`.trim();
|
|
||||||
|
|
||||||
// In dev we bind the dashboard to 0.0.0.0 so the server is reachable from
|
// In dev we bind the dashboard to 0.0.0.0 so the server is reachable from
|
||||||
// mobile devices and other machines on the LAN for testing. Production
|
// mobile devices and other machines on the LAN for testing. Production
|
||||||
@@ -66,16 +66,16 @@ const ENTRY = path.resolve(process.cwd(), "packages/cli/src/bin.ts");
|
|||||||
|
|
||||||
// Spawn node directly (no shell) so the inspector attaches to the real app
|
// Spawn node directly (no shell) so the inspector attaches to the real app
|
||||||
// process and there's no parent/child wrapper consuming --inspect.
|
// process and there's no parent/child wrapper consuming --inspect.
|
||||||
|
// Inspector flags are CLI args here so they apply only to this process and
|
||||||
|
// don't propagate to grandchildren via NODE_OPTIONS.
|
||||||
function runApp(extraArgs) {
|
function runApp(extraArgs) {
|
||||||
const tsx = spawn(process.execPath, [
|
const tsx = spawn(process.execPath, [
|
||||||
|
...inspectFlags,
|
||||||
"--require", PRELOAD,
|
"--require", PRELOAD,
|
||||||
"--import", `file://${LOADER}`,
|
"--import", `file://${LOADER}`,
|
||||||
ENTRY,
|
ENTRY,
|
||||||
...extraArgs,
|
...extraArgs,
|
||||||
], {
|
], { stdio: "inherit" });
|
||||||
stdio: "inherit",
|
|
||||||
env: { ...process.env, NODE_OPTIONS: runNodeOptions },
|
|
||||||
});
|
|
||||||
tsx.on("close", (c) => process.exit(c ?? 1));
|
tsx.on("close", (c) => process.exit(c ?? 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user