From 7e86d06bde9def8acf5ae3521e9f274fb427f218 Mon Sep 17 00:00:00 2001 From: Braden Wong <13159333+braden-w@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:19:29 -0700 Subject: [PATCH] feat(server): improve server startup error handling Add structured error handling for server startup failures: - Catch Bun.serve() errors and wrap in ServerStartError NamedError - Pass through original Bun error messages (e.g., "Failed to start server. Is port 4096 in use?") - Format errors in FormatError() to display user-friendly messages - Prevents generic "unexpected error" messages for common server startup issues --- packages/opencode/src/cli/error.ts | 5 ++++ packages/opencode/src/server/server.ts | 34 ++++++++++++++++++++------ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/packages/opencode/src/cli/error.ts b/packages/opencode/src/cli/error.ts index 261206a1..f2ce6645 100644 --- a/packages/opencode/src/cli/error.ts +++ b/packages/opencode/src/cli/error.ts @@ -1,6 +1,7 @@ import { Config } from "../config/config" import { MCP } from "../mcp" import { UI } from "./ui" +import { Server } from "../server/server" export function FormatError(input: unknown) { if (MCP.Failed.isInstance(input)) @@ -13,4 +14,8 @@ export function FormatError(input: unknown) { ].join("\n") if (UI.CancelledError.isInstance(input)) return "" + + if (Server.ServerStartError.isInstance(input)) { + return input.data.message + } } diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index a3b34f41..102fd2cc 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -766,12 +766,32 @@ export namespace Server { } export function listen(opts: { port: number; hostname: string }) { - const server = Bun.serve({ - port: opts.port, - hostname: opts.hostname, - idleTimeout: 0, - fetch: app().fetch, - }) - return server + try { + const server = Bun.serve({ + port: opts.port, + hostname: opts.hostname, + idleTimeout: 0, + fetch: app().fetch, + }) + return server + } catch (error) { + if (error instanceof Error) { + throw new ServerStartError({ + port: opts.port, + hostname: opts.hostname, + message: error.message, + }) + } + throw error + } } + + export const ServerStartError = NamedError.create( + "ServerStartError", + z.object({ + port: z.number(), + hostname: z.string(), + message: z.string(), + }), + ) }