Skip to content
Draft
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
82 changes: 57 additions & 25 deletions gui/src/pages/gui/StreamError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const StreamErrorDialog = ({ error }: StreamErrorProps) => {
modelTitle,
providerName,
apiKeyUrl,
helpUrl,
hideGithubIssue,
} = useMemo(() => analyzeError(error, selectedModel), [error, selectedModel]);

const handleRefreshProfiles = () => {
Expand Down Expand Up @@ -284,14 +286,42 @@ const StreamErrorDialog = ({ error }: StreamErrorProps) => {
</div>
)}

<div>
<span className="text-base font-medium">Report this error</span>
<div className="mt-2 flex flex-row flex-wrap items-center gap-2">
<GhostButton
className="flex flex-row items-center gap-2 rounded px-3 py-1.5"
onClick={() => {
const issueTitle = `Error: ${selectedModel?.title || "Model"} - ${statusCode || "Unknown error"}`;
const issueBody = `**Error Details**
{helpUrl ? (
<div>
<span className="text-base font-medium">
Get help with this error
</span>
<div className="mt-2 flex flex-row flex-wrap items-center gap-2">
<GhostButton
className="flex flex-row items-center gap-2 rounded px-3 py-1.5"
onClick={() => {
ideMessenger.post("openUrl", helpUrl);
}}
>
<ArrowTopRightOnSquareIcon className="h-5 w-5" />
<span className="xs:flex hidden">View help documentation</span>
</GhostButton>
<GhostButton
className="flex flex-row items-center gap-2 rounded px-3 py-1.5"
onClick={() => {
ideMessenger.post("openUrl", DISCORD_LINK);
}}
>
<DiscordIcon className="h-5 w-5" />
<span className="xs:flex hidden">Discord</span>
</GhostButton>
</div>
</div>
) : (
<div>
<span className="text-base font-medium">Report this error</span>
<div className="mt-2 flex flex-row flex-wrap items-center gap-2">
{!hideGithubIssue && (
<GhostButton
className="flex flex-row items-center gap-2 rounded px-3 py-1.5"
onClick={() => {
const issueTitle = `Error: ${selectedModel?.title || "Model"} - ${statusCode || "Unknown error"}`;
const issueBody = `**Error Details**

Model: ${selectedModel?.title || "Unknown"}
Provider: ${selectedModel?.provider || "Unknown"}
Expand All @@ -305,24 +335,26 @@ ${parsedError}
**Additional Context**
Please add any additional context about the error here
`;
const url = `https://github.com/continuedev/continue/issues/new?title=${encodeURIComponent(issueTitle)}&body=${encodeURIComponent(issueBody)}`;
ideMessenger.post("openUrl", url);
}}
>
<GithubIcon className="h-5 w-5" />
<span className="xs:flex hidden">Open GitHub issue</span>
</GhostButton>
<GhostButton
className="flex flex-row items-center gap-2 rounded px-3 py-1.5"
onClick={() => {
ideMessenger.post("openUrl", DISCORD_LINK);
}}
>
<DiscordIcon className="h-5 w-5" />
<span className="xs:flex hidden">Discord</span>
</GhostButton>
const url = `https://github.com/continuedev/continue/issues/new?title=${encodeURIComponent(issueTitle)}&body=${encodeURIComponent(issueBody)}`;
ideMessenger.post("openUrl", url);
}}
>
<GithubIcon className="h-5 w-5" />
<span className="xs:flex hidden">Open GitHub issue</span>
</GhostButton>
)}
<GhostButton
className="flex flex-row items-center gap-2 rounded px-3 py-1.5"
onClick={() => {
ideMessenger.post("openUrl", DISCORD_LINK);
}}
>
<DiscordIcon className="h-5 w-5" />
<span className="xs:flex hidden">Discord</span>
</GhostButton>
</div>
</div>
</div>
)}
</div>
);
};
Expand Down
51 changes: 51 additions & 0 deletions gui/src/util/errorAnalysis.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ describe("errorAnalysis", () => {
modelTitle: "Chat model",
providerName: "the model provider",
apiKeyUrl: undefined,
helpUrl: undefined,
hideGithubIssue: undefined,
});
});

Expand All @@ -27,6 +29,8 @@ describe("errorAnalysis", () => {
modelTitle: "Chat model",
providerName: "the model provider",
apiKeyUrl: undefined,
helpUrl: undefined,
hideGithubIssue: undefined,
});
});

Expand All @@ -40,6 +44,8 @@ describe("errorAnalysis", () => {
modelTitle: "Chat model",
providerName: "the model provider",
apiKeyUrl: undefined,
helpUrl: undefined,
hideGithubIssue: undefined,
});
});

Expand All @@ -54,6 +60,8 @@ describe("errorAnalysis", () => {
modelTitle: "Chat model",
providerName: "the model provider",
apiKeyUrl: undefined,
helpUrl: undefined,
hideGithubIssue: undefined,
});
});

Expand All @@ -68,6 +76,8 @@ describe("errorAnalysis", () => {
modelTitle: "Chat model",
providerName: "the model provider",
apiKeyUrl: undefined,
helpUrl: undefined,
hideGithubIssue: undefined,
});
});
});
Expand Down Expand Up @@ -530,6 +540,47 @@ describe("errorAnalysis", () => {
expect(result.parsedError).toBe("Request timeout");
expect(result.statusCode).toBe(undefined);
});

it("should handle OpenAI organization verification error", () => {
const error = new Error(
'HTTP 400 Bad Request\n\n{"message":"Your organization must be verified to generate reasoning summaries. Please go to: https://platform.openai.com/settings/organization/general and click on Verify Organization. If you just verified, it can take up to 15 minutes for access to propagate.","type":"invalid_request_error","param":"reasoning.summary","code":"unsupported_value"}',
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Test expects OpenAI verification handling even though the error message lacks "openai", which contradicts the detection logic requiring that substring and will fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At gui/src/util/errorAnalysis.test.ts, line 546:

<comment>Test expects OpenAI verification handling even though the error message lacks "openai", which contradicts the detection logic requiring that substring and will fail.</comment>

<file context>
@@ -530,6 +540,47 @@ describe("errorAnalysis", () => {
+
+      it("should handle OpenAI organization verification error", () => {
+        const error = new Error(
+          'HTTP 400 Bad Request\n\n{"message":"Your organization must be verified to generate reasoning summaries. Please go to: https://platform.openai.com/settings/organization/general and click on Verify Organization. If you just verified, it can take up to 15 minutes for access to propagate.","type":"invalid_request_error","param":"reasoning.summary","code":"unsupported_value"}',
+        );
+        const selectedModel = {
</file context>
Suggested change
'HTTP 400 Bad Request\n\n{"message":"Your organization must be verified to generate reasoning summaries. Please go to: https://platform.openai.com/settings/organization/general and click on Verify Organization. If you just verified, it can take up to 15 minutes for access to propagate.","type":"invalid_request_error","param":"reasoning.summary","code":"unsupported_value"}',
'HTTP 400 Bad Request\n\n{"message":"OpenAI: Your organization must be verified to generate reasoning summaries. Please go to: https://platform.openai.com/settings/organization/general and click on Verify Organization. If you just verified, it can take up to 15 minutes for access to propagate.","type":"invalid_request_error","param":"reasoning.summary","code":"unsupported_value"}',
Fix with Cubic

);
const selectedModel = {
title: "GPT-4o",
provider: "openai",
};
const result = analyzeError(error, selectedModel);

expect(result.helpUrl).toBe(
"https://help.openai.com/en/articles/10910291-api-organization-verification",
);
expect(result.hideGithubIssue).toBe(true);
expect(result.providerName).toBe("OpenAI");
});

it("should match OpenAI verification error case-insensitively", () => {
const error = new Error(
"Error from OpenAI: Your Organization Must Be Verified To Generate Reasoning Summaries.",
);
const result = analyzeError(error, null);

expect(result.helpUrl).toBe(
"https://help.openai.com/en/articles/10910291-api-organization-verification",
);
expect(result.hideGithubIssue).toBe(true);
});

it("should not match partial OpenAI verification error messages", () => {
const error1 = new Error("Your organization must be verified");
const result1 = analyzeError(error1, null);
expect(result1.helpUrl).toBe(undefined);
expect(result1.hideGithubIssue).toBe(undefined);

const error2 = new Error("OpenAI error occurred");
const result2 = analyzeError(error2, null);
expect(result2.helpUrl).toBe(undefined);
expect(result2.hideGithubIssue).toBe(undefined);
});
});
});
});
19 changes: 19 additions & 0 deletions gui/src/util/errorAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export interface ErrorAnalysis {
modelTitle: string;
providerName: string;
apiKeyUrl?: string;
helpUrl?: string;
hideGithubIssue?: boolean;
}

function parseErrorMessage(fullErrMsg: string): string {
Expand Down Expand Up @@ -66,6 +68,8 @@ export function analyzeError(

let message: undefined | string = undefined;
let statusCode: undefined | number = undefined;
let helpUrl: undefined | string = undefined;
let hideGithubIssue: undefined | boolean = undefined;

// Attempt to get error message and status code from error
if (
Expand Down Expand Up @@ -97,12 +101,27 @@ export function analyzeError(
}
}

// Check for OpenAI organization verification error
if (
message &&
message.toLowerCase().includes("openai") &&
message
.toLowerCase()
.includes("organization must be verified to generate reasoning summaries")
) {
helpUrl =
"https://help.openai.com/en/articles/10910291-api-organization-verification";
hideGithubIssue = true;
}

return {
parsedError,
statusCode,
message,
modelTitle,
providerName,
apiKeyUrl,
helpUrl,
hideGithubIssue,
};
}
Loading