diff --git a/apps/cli/src/next/commands/functions/deploy/deploy.integration.test.ts b/apps/cli/src/next/commands/functions/deploy/deploy.integration.test.ts index d4d7e30b0b..0b73309418 100644 --- a/apps/cli/src/next/commands/functions/deploy/deploy.integration.test.ts +++ b/apps/cli/src/next/commands/functions/deploy/deploy.integration.test.ts @@ -1466,6 +1466,34 @@ describe("functions deploy", () => { }).pipe(Effect.ensuring(cleanupTempDir(tempDir))); }); + it.live("fails with a contextual error when Docker bundling produces no eszip output", () => { + const tempDir = makeTempDir(); + const child = mockChildProcessSpawner({ exitCode: 0 }); + + return Effect.gen(function* () { + yield* Effect.promise(() => writeProjectConfig(tempDir)); + yield* Effect.promise(() => writeLocalFunction(tempDir, "hello-world")); + + const { out, layer } = setup(tempDir, { + rawArgs: ["functions", "deploy", "hello-world", "--use-docker"], + childLayer: child.layer, + }); + + const error = yield* functionsDeploy({ + ...BASE_FLAGS, + functionNames: ["hello-world"], + useDocker: true, + }).pipe(Effect.provide(layer), Effect.flip); + + expect(error).toBeInstanceOf(Error); + if (error instanceof Error) { + expect(error.message).toContain("failed to open eszip:"); + expect(error.message).toContain("output.eszip"); + } + expect(out.stderrText).toContain("Bundling Function: hello-world\n"); + }).pipe(Effect.ensuring(cleanupTempDir(tempDir))); + }); + it.live( "accepts nullable optional fields when listing remote functions for Docker deploys", () => { diff --git a/apps/cli/src/shared/functions/deploy.ts b/apps/cli/src/shared/functions/deploy.ts index 8f626e673b..0e2fb6b28c 100644 --- a/apps/cli/src/shared/functions/deploy.ts +++ b/apps/cli/src/shared/functions/deploy.ts @@ -1404,7 +1404,13 @@ const bundleFunctionWithDocker = Effect.fnUntraced(function* ( return yield* Effect.fail(new Error(`failed to bundle function: exit ${result.exitCode}`)); } - const eszip = yield* Effect.tryPromise(() => readFile(outputPath)); + const eszip = yield* Effect.tryPromise({ + try: () => readFile(outputPath), + catch: (error) => + new Error( + `failed to open eszip: ${error instanceof Error ? error.message : String(error)}`, + ), + }); const compressed = new Uint8Array( Buffer.concat([ Buffer.from(COMPRESSED_ESZIP_MAGIC),