diff --git a/packages/cli/src/commands/handlers/stats.ts b/packages/cli/src/commands/handlers/stats.ts
index 3befbc457ee..3502ac5efe2 100644
--- a/packages/cli/src/commands/handlers/stats.ts
+++ b/packages/cli/src/commands/handlers/stats.ts
@@ -1,4 +1,4 @@
-import { OpenCode, type SessionStatsInfo } from "@opencode-ai/client"
+import { ClientError, OpenCode, type SessionStatsInfo } from "@opencode-ai/client"
import { Service } from "@opencode-ai/client/effect/service"
import { Effect, Option } from "effect"
import { EOL } from "node:os"
@@ -67,10 +67,13 @@ export default Runtime.handler(Commands.commands.stats, (input) =>
),
)
-function request(url: string, run: (signal: AbortSignal) => Promise) {
+export function request(url: string, run: (signal: AbortSignal) => Promise) {
return Effect.tryPromise({
try: () => run(AbortSignal.timeout(30_000)),
- catch: (cause) => new Error(`Could not reach server at ${url}`, { cause }),
+ catch: (cause) =>
+ cause instanceof ClientError && cause.reason === "Transport"
+ ? new Error(`Could not reach server at ${url}`, { cause })
+ : cause,
})
}
diff --git a/packages/cli/test/stats.test.ts b/packages/cli/test/stats.test.ts
index 06f2e6c1859..0fdea8ad08c 100644
--- a/packages/cli/test/stats.test.ts
+++ b/packages/cli/test/stats.test.ts
@@ -1,6 +1,7 @@
import { describe, expect, test } from "bun:test"
-import type { SessionStatsInfo } from "@opencode-ai/client"
-import { renderStats } from "../src/commands/handlers/stats"
+import { ClientError, type SessionStatsInfo } from "@opencode-ai/client"
+import { Effect } from "effect"
+import { renderStats, request } from "../src/commands/handlers/stats"
const tools = {
mode: "detail",
@@ -121,6 +122,26 @@ describe("stats rendering", () => {
})
})
+describe("stats requests", () => {
+ test("maps transport failures to the server URL", async () => {
+ const cause = new ClientError("Transport")
+ const error = await Effect.runPromise(Effect.flip(request("http://localhost:4096", () => Promise.reject(cause))))
+ expect(error).toEqual(new Error("Could not reach server at http://localhost:4096", { cause }))
+ })
+
+ test("preserves declared API errors", async () => {
+ const cause = { _tag: "InvalidRequestError", message: "Stats range must end after it starts" } as const
+ const error = await Effect.runPromise(Effect.flip(request("http://localhost:4096", () => Promise.reject(cause))))
+ expect(error).toBe(cause)
+ })
+
+ test("preserves unexpected response failures", async () => {
+ const cause = new ClientError("UnexpectedStatus", { cause: { status: 500 } })
+ const error = await Effect.runPromise(Effect.flip(request("http://localhost:4096", () => Promise.reject(cause))))
+ expect(error).toBe(cause)
+ })
+})
+
function options(input: Partial[1]> = {}): Parameters[1] {
return {
label: "2026 so far",