Skip to content
Open
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
3 changes: 2 additions & 1 deletion packages/opencode/src/provider/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ function message(providerID: ProviderV2.ID, e: APICallError) {
return msg
}

return `${msg}: ${e.responseBody}`
const body = e.responseBody.length > 200 ? e.responseBody.slice(0, 200) + "..." : e.responseBody
return `${msg}: ${body}`
}).trim()
}

Expand Down
23 changes: 23 additions & 0 deletions packages/opencode/src/session/message-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,17 @@ export function latest(msgs: WithParts[]) {
return { user, assistant, finished, tasks }
}

const TRANSIENT_CODES = new Set(["ECONNRESET", "ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND", "EAI_AGAIN", "ENETUNREACH", "EPIPE"])
const TRANSIENT_PATTERNS = ["failed to fetch", "network connection was lost", "network request failed", "socket hang up", "unexpected end of data", "premature close", "response closed without sending", "load failed", "fetch failed", "body is unusable"]

function isTransientNetworkError(e: unknown): e is Error {
if (!(e instanceof Error)) return false
const code = (e as Error & { code?: string }).code
if (code && TRANSIENT_CODES.has(code)) return true
const msg = e.message.toLowerCase()
return TRANSIENT_PATTERNS.some((p) => msg.includes(p))
}

export function fromError(
e: unknown,
ctx: { providerID: ProviderV2.ID; aborted?: boolean },
Expand Down Expand Up @@ -710,6 +721,18 @@ export function fromError(
},
{ cause: e },
).toObject()
case isTransientNetworkError(e):
return new APIError(
{
message: e.message,
isRetryable: true,
metadata: {
type: "network_error",
code: e.name,
},
},
{ cause: e },
).toObject()
case e instanceof Error:
return new NamedError.Unknown({ message: errorMessage(e) }, { cause: e }).toObject()
default:
Expand Down
Loading