Repository navigation
fix(opencode): show a readable message when a provider error is <none> #24734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0d06ff8
a59cd7a
cd9e227
7de6d57
bfcd2eb
de4ae43
58215a0
4398b5b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /** OpenCode stores `<none>` when it cannot read the provider body. */ | ||
| export function readableProviderErrorMessage( | ||
| message?: string, | ||
| status?: number, | ||
| body?: string, | ||
| ): string | undefined { | ||
| const text = message?.trim() ?? ""; | ||
| if (text && text.toLowerCase() !== "<none>") return text; | ||
| const title = body | ||
| ?.match(/<title[^>]*>([^<]*)<\/title>/i)?.[1] | ||
| ?.replace(/\s+/g, " ") | ||
| .trim(); | ||
| if (title) return typeof status === "number" ? `${title} (HTTP ${status}).` : title; | ||
| if (typeof status === "number") return `The model provider failed the request (HTTP ${status}).`; | ||
| return text | ||
| ? "The model provider failed the request and did not include an error message." | ||
| : undefined; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -56,6 +56,7 @@ import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | |
| import * as OpenCode2Client from "./OpenCode2Client.ts"; | ||
| import * as OpenCode2Server from "./OpenCode2Server.ts"; | ||
| import * as OpenCodeRuntime from "../OpenCodeRuntime.ts"; | ||
| import { readableProviderErrorMessage } from "../providerErrorMessage.ts"; | ||
| import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | ||
| import { buildRuntimeInstructions } from "@t3tools/provider-core/server/runtimeInstructions"; | ||
| import { t3OrchestrationSystemPrompt } from "@t3tools/provider-core/server/orchestrationInstructions"; | ||
|
|
@@ -1073,7 +1074,7 @@ export const make = Effect.fn("OpenCode2Adapter.make")(function* (instanceId: Pr | |
| retryDelayMs: Math.max(0, Math.trunc(delayMs)), | ||
| }, | ||
| failure: makeProviderFailure({ | ||
| message: error.message, | ||
| message: readableProviderErrorMessage(error.message, error.status, error.response?.body), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| code: error.type, | ||
| class: "provider_error", | ||
| retryable: true, | ||
|
|
@@ -2125,15 +2126,15 @@ export const make = Effect.fn("OpenCode2Adapter.make")(function* (instanceId: Pr | |
| case "session.execution.interrupted": | ||
| return yield* endExecution(state, turn, { status: "interrupted" }); | ||
| case "session.execution.failed": { | ||
| const { type, message, status } = event.data.error; | ||
| const { type, message, status, response } = event.data.error; | ||
| // OpenCode types an empty balance as provider.quota too, but it answers | ||
| // that with HTTP 402 and it never resets. Usage windows and budgets are 429. | ||
| const usageLimit = | ||
| (type === "provider.quota" && status !== 402) || type === "provider.rate-limit"; | ||
| return yield* endExecution(state, turn, { | ||
| status: "failed", | ||
| failure: makeProviderFailure({ | ||
| message, | ||
| message: readableProviderErrorMessage(message, status, response?.body), | ||
| code: type, | ||
| class: usageLimit ? "usage_limit" : "provider_error", | ||
| }), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔎 Supported by static analysis
Script executed:
Repository: pingdotgg/t3code
Length of output: 5889
Script executed:
Repository: pingdotgg/t3code
Length of output: 41765
Script executed:
Repository: pingdotgg/t3code
Length of output: 19716
Script executed:
Repository: pingdotgg/t3code
Length of output: 10802
Script executed:
Repository: pingdotgg/t3code
Length of output: 44864
Script executed:
Repository: pingdotgg/t3code
Length of output: 14542
Script executed:
Repository: pingdotgg/t3code
Length of output: 10241
Reuse the sanitized failure message for the legacy session update.
The V2 paths sanitize the title through
makeProviderFailure. The legacy path sends the raw title toupdateProviderSessionfirst. That emits an unboundedlastErrorin aprovider-session.updatedevent.Suggested fix