Skip to content
Merged
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
7 changes: 7 additions & 0 deletions .changeset/fix-multiworker-build-errors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"wrangler": patch
---

Display build errors for auxiliary workers in multi-worker mode

Previously, when running `wrangler dev` with multiple `-c` config flags (multi-worker mode), build errors from auxiliary/secondary workers were only logged at debug level, causing Wrangler to silently hang. Build errors from all workers are now displayed at error level so you can see what went wrong and fix it.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { describe, test } from "vitest";
import { DevEnv } from "../../../api/startDevWorker/DevEnv";
import { mockConsoleMethods } from "../../helpers/mock-console";

describe("DevEnv", () => {
const std = mockConsoleMethods();

describe("handleErrorEvent", () => {
test("should format esbuild BuildFailure errors nicely for BundlerController", ({
expect,
}) => {
const devEnv = new DevEnv();

// Create an esbuild-like BuildFailure with errors and warnings arrays
const buildFailure = Object.assign(new Error("Build failed"), {
errors: [
{
id: "",
pluginName: "",
text: 'Could not resolve "some-missing-module"',
location: null,
notes: [],
detail: undefined,
},
],
warnings: [],
});

devEnv.dispatch({
type: "error",
reason: "Failed to construct initial bundle",
cause: buildFailure,
source: "BundlerController",
data: undefined,
});

expect(std.err).toContain("Build failed with 1 error");
expect(std.err).toContain('Could not resolve "some-missing-module"');

void devEnv.teardown();
});

test("should format esbuild BuildFailure from cause for BundlerController", ({
expect,
}) => {
const devEnv = new DevEnv();

// Create an esbuild-like BuildFailure nested in cause
const innerFailure = Object.assign(new Error("Build failed"), {
errors: [
{
id: "",
pluginName: "",
text: "Syntax error in worker code",
location: null,
notes: [],
detail: undefined,
},
],
warnings: [],
});
const outerError = new Error("Initial build failed.");
outerError.cause = innerFailure;

devEnv.dispatch({
type: "error",
reason: "Failed to construct initial bundle",
cause: outerError,
source: "BundlerController",
data: undefined,
});

expect(std.err).toContain("Build failed with 1 error");
expect(std.err).toContain("Syntax error in worker code");

void devEnv.teardown();
});

test("should log non-esbuild BundlerController errors with just the message", ({
expect,
}) => {
const devEnv = new DevEnv();

const buildError = new Error("Custom build command failed");

devEnv.dispatch({
type: "error",
reason: "Custom build failed",
cause: buildError,
source: "BundlerController",
data: { config: undefined, filePath: "src/index.ts" },
});

expect(std.err).toContain("Custom build command failed");

void devEnv.teardown();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ export class BundlerController extends Controller {
entrypointSource: readFileSync(entrypointPath, "utf8"),
});
} catch (err) {
logger.error("Custom build failed:", err);
this.emitErrorEvent({
type: "error",
reason: "Custom build failed",
Expand Down Expand Up @@ -335,9 +334,6 @@ export class BundlerController extends Controller {
try {
this.#tmpDir = getWranglerTmpDir(event.config.projectRoot, "dev");
} catch (e) {
logger.error(
"Failed to create temporary directory to store built files."
);
this.emitErrorEvent({
type: "error",
reason: "Failed to create temporary directory to store built files.",
Expand All @@ -348,7 +344,6 @@ export class BundlerController extends Controller {
}

void this.#startCustomBuild(event.config).catch((err) => {
logger.error("Failed to run custom build:", err);
this.emitErrorEvent({
type: "error",
reason: "Failed to run custom build",
Expand All @@ -358,7 +353,6 @@ export class BundlerController extends Controller {
});
});
void this.#startBundle(event.config).catch((err) => {
logger.error("Failed to start bundler:", err);
this.emitErrorEvent({
type: "error",
reason: "Failed to start bundler",
Expand All @@ -368,7 +362,6 @@ export class BundlerController extends Controller {
});
});
void this.#ensureWatchingAssets(event.config).catch((err) => {
logger.error("Failed to watch assets:", err);
this.emitErrorEvent({
type: "error",
reason: "Failed to watch assets",
Expand Down
16 changes: 15 additions & 1 deletion packages/wrangler/src/api/startDevWorker/DevEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import assert from "node:assert";
import { EventEmitter } from "node:events";
import { ParseError, UserError } from "@cloudflare/workers-utils";
import { MiniflareCoreError } from "miniflare";
import { logger, runWithLogLevel } from "../../logger";
import {
isBuildFailure,
isBuildFailureFromCause,
} from "../../deployment-bundle/build-failures";
import { logBuildFailure, logger, runWithLogLevel } from "../../logger";
import { BundlerController } from "./BundlerController";
import { ConfigController } from "./ConfigController";
import { LocalRuntimeController } from "./LocalRuntimeController";
Expand Down Expand Up @@ -156,6 +160,16 @@ export class DevEnv extends EventEmitter implements ControllerBus {
) {
logger.error(event.cause);
}
// Build errors are recoverable by fixing the code and saving
else if (event.source === "BundlerController") {
if (isBuildFailure(event.cause)) {
logBuildFailure(event.cause.errors, event.cause.warnings);
} else if (isBuildFailureFromCause(event.cause)) {
logBuildFailure(event.cause.cause.errors, event.cause.cause.warnings);
} else {
logger.error(event.cause.message);
}
}
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
// if other knowable + recoverable errors occur, handle them here
else {
// otherwise, re-emit the unknowable errors to the top-level
Expand Down
Loading