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
This commit is contained in:
Braden Wong 2025-07-22 10:19:29 -07:00
parent 01f8d3b05d
commit 7e86d06bde
2 changed files with 32 additions and 7 deletions

View file

@ -1,6 +1,7 @@
import { Config } from "../config/config" import { Config } from "../config/config"
import { MCP } from "../mcp" import { MCP } from "../mcp"
import { UI } from "./ui" import { UI } from "./ui"
import { Server } from "../server/server"
export function FormatError(input: unknown) { export function FormatError(input: unknown) {
if (MCP.Failed.isInstance(input)) if (MCP.Failed.isInstance(input))
@ -13,4 +14,8 @@ export function FormatError(input: unknown) {
].join("\n") ].join("\n")
if (UI.CancelledError.isInstance(input)) return "" if (UI.CancelledError.isInstance(input)) return ""
if (Server.ServerStartError.isInstance(input)) {
return input.data.message
}
} }

View file

@ -766,12 +766,32 @@ export namespace Server {
} }
export function listen(opts: { port: number; hostname: string }) { export function listen(opts: { port: number; hostname: string }) {
const server = Bun.serve({ try {
port: opts.port, const server = Bun.serve({
hostname: opts.hostname, port: opts.port,
idleTimeout: 0, hostname: opts.hostname,
fetch: app().fetch, idleTimeout: 0,
}) fetch: app().fetch,
return server })
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(),
}),
)
} }