Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/fix-node-v26-silent-exit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"wrangler": patch
---

Fix silent exit with no error message on Node.js v26

`wrangler` was silently exiting with code 1 on Node.js v26 with no error message shown. This release fixes two independent issues that caused this behaviour:

1. A stale Node.js flag that caused unexpected behaviour on Node.js v26 has been removed.

2. If an error occurs in a situation where the normal error reporting path itself fails, `wrangler` now always prints the original error to stderr so the cause is visible rather than silently disappearing.
5 changes: 3 additions & 2 deletions packages/miniflare/test/plugins/browser/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async function sendMessage(ws: WebSocket, message: unknown) {
const chunks: Uint8Array[] = [firstChunk];
for (
let i = FIRST_CHUNK_DATA_SIZE;
i < data.length;
i < encodedUint8Array.length;
i += MAX_MESSAGE_SIZE
) {
chunks.push(encodedUint8Array.slice(i, i + MAX_MESSAGE_SIZE));
Expand Down Expand Up @@ -63,6 +63,7 @@ async function waitForClosedConnection(ws: WebSocket): Promise<void> {
}

const BROWSER_RENDERING_RETRY = {
timeout: 120_000,
retry: {
condition: /Chrome readiness probe .* timed out|Test timed out/i,
count: 3,
Expand All @@ -83,7 +84,7 @@ export default {

// We need to run browser rendering tests in a serial manner to avoid a race condition installing the browser.
// We set the timeout quite high here as one of these tests will need to download the Chrome headless browser.
describe.sequential("browser rendering", { timeout: 20_000 }, () => {
describe.sequential("browser rendering", { timeout: 120_000 }, () => {
// The CLI spinner outputs to stdout, so we mute it during tests
beforeEach(() => {
vi.spyOn(process.stdout, "write").mockImplementation(() => true);
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Main CLI for Cloudflare Workers. ~2k-line yargs command tree in `src/index.ts`.
- `src/` — CLI source
- `src/__tests__/` — Unit tests, helpers in `src/__tests__/helpers/`
- `e2e/` — E2E tests, requires Cloudflare credentials
- `bin/wrangler.js` — Shim that spawns Node with `--experimental-vm-modules`
- `bin/wrangler.js` — Shim that spawns Node to run `wrangler-dist/cli.js`, forwarding stdio and IPC
- `bin/cf-wrangler.js` — `cf-wrangler` delegate entrypoint. Owns verb dispatch and argv parsing (`parseCfWranglerArgs`, `parseCfWranglerBuildArgs`); hands off to `runCfWranglerDev` / `runCfWranglerBuild` from `wrangler-dist/cli.js` in-process (no re-spawn — the parent tool owns the Node runtime)
- `src/cf-wrangler/` — The `cf-wrangler` delegate entrypoint (see below)
- `templates/` — Worker templates
Expand Down
1 change: 0 additions & 1 deletion packages/wrangler/bin/wrangler.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ Consider using a Node.js version manager such as https://volta.sh/ or https://gi
process.execPath,
[
"--no-warnings",
"--experimental-vm-modules",
...process.execArgv,
Comment thread
matingathani marked this conversation as resolved.
path.join(__dirname, "../wrangler-dist/cli.js"),
...process.argv.slice(2),
Expand Down
15 changes: 14 additions & 1 deletion packages/wrangler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2419,7 +2419,20 @@ export async function main(argv: string[]): Promise<void> {
if (dispatcher) {
dispatchGenericCommandErrorEvent(dispatcher, startTime, e);
}
await handleError(e, configArgs, argv);
try {
await handleError(e, configArgs, argv);
} catch (handleErrorErr) {
// handleError itself threw before it could log the error.
// Fall back to raw stderr so the user always sees something.
const message = e instanceof Error ? (e.stack ?? e.message) : String(e);
const handlerMessage =
handleErrorErr instanceof Error
? (handleErrorErr.stack ?? handleErrorErr.message)
: String(handleErrorErr);
process.stderr.write(
`\n${message}${handlerMessage ? `\n\n(error handler also failed: ${handlerMessage})` : ""}\n`
);
}
Comment thread
matingathani marked this conversation as resolved.
throw e;
}
} finally {
Expand Down
Loading