fix(auth): show actionable provider re-auth errors (#450)
This commit is contained in:
@@ -22,6 +22,7 @@ import type { StreamPhase, ToolPopupContent } from './message/types';
|
||||
import { deriveMessageRole } from './message/messageRole';
|
||||
import { filterVisibleParts } from './message/partUtils';
|
||||
import { flattenAssistantTextParts } from '@/lib/messages/messageText';
|
||||
import { isLikelyProviderAuthFailure, PROVIDER_AUTH_FAILURE_MESSAGE } from '@/lib/messages/providerAuthError';
|
||||
import { FadeInOnReveal } from './message/FadeInOnReveal';
|
||||
import type { TurnGroupingContext } from './hooks/useTurnGrouping';
|
||||
|
||||
@@ -646,6 +647,9 @@ const ChatMessage: React.FC<ChatMessageProps> = ({
|
||||
if (errorName === 'SessionRetry') {
|
||||
return `Opencode failed to send a message. Retry attempt info: \n\`${detail}\``;
|
||||
}
|
||||
if (isLikelyProviderAuthFailure(detail)) {
|
||||
return PROVIDER_AUTH_FAILURE_MESSAGE;
|
||||
}
|
||||
return `Opencode failed to send message with error:\n\`${detail}\``;
|
||||
}, [isUser, message.info]);
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
export const PROVIDER_AUTH_FAILURE_MESSAGE = "Authentication failed for this provider. Please re-authenticate and retry.";
|
||||
|
||||
export const isLikelyProviderAuthFailure = (value: unknown): boolean => {
|
||||
if (typeof value !== "string") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const detail = value.toLowerCase().trim();
|
||||
if (!detail) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
detail.includes("token refresh failed") ||
|
||||
detail.includes("unauthorized") ||
|
||||
detail.includes("invalid token") ||
|
||||
detail.includes("expired token")
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const hasOauth = detail.includes("oauth");
|
||||
const hasOauthFailure =
|
||||
detail.includes("failed") || detail.includes("invalid") || detail.includes("expired");
|
||||
if (hasOauth && hasOauthFailure) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const has401 = /\b401\b/.test(detail);
|
||||
const hasAuthContext =
|
||||
detail.includes("auth") || detail.includes("token") || detail.includes("unauthorized");
|
||||
|
||||
return has401 && hasAuthContext;
|
||||
};
|
||||
@@ -4,6 +4,7 @@ import { devtools, persist, createJSONStorage } from "zustand/middleware";
|
||||
import type { Message, Part } from "@opencode-ai/sdk/v2";
|
||||
import { opencodeClient } from "@/lib/opencode/client";
|
||||
import { isExecutionForkMetaText } from "@/lib/messages/executionMeta";
|
||||
import { isLikelyProviderAuthFailure, PROVIDER_AUTH_FAILURE_MESSAGE } from "@/lib/messages/providerAuthError";
|
||||
import type { SessionMemoryState, MessageStreamLifecycle, AttachedFile } from "./types/sessionTypes";
|
||||
import { MEMORY_LIMITS, getMemoryLimits, getBackgroundTrimLimit } from "./types/sessionTypes";
|
||||
import {
|
||||
@@ -787,6 +788,8 @@ export const useMessageStore = create<MessageStore>()(
|
||||
return { abortControllers: nextControllers };
|
||||
});
|
||||
return;
|
||||
} else if (isLikelyProviderAuthFailure(error.message)) {
|
||||
errorMessage = PROVIDER_AUTH_FAILURE_MESSAGE;
|
||||
} else if (error.message) {
|
||||
errorMessage = error.message;
|
||||
}
|
||||
@@ -814,6 +817,8 @@ export const useMessageStore = create<MessageStore>()(
|
||||
errorMessage = "OpenCode is restarting. Please wait a moment and try again.";
|
||||
} else if (error.message?.includes("504") || error.message?.includes("Gateway")) {
|
||||
errorMessage = "Gateway timeout - your message is being processed. Please wait for response.";
|
||||
} else if (isLikelyProviderAuthFailure(error.message)) {
|
||||
errorMessage = PROVIDER_AUTH_FAILURE_MESSAGE;
|
||||
} else if (error.message) {
|
||||
errorMessage = error.message;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,9 @@ export const fetchQuota = async () => {
|
||||
providerName,
|
||||
ok: false,
|
||||
configured: true,
|
||||
error: `API error: ${response.status}`
|
||||
error: response.status === 401
|
||||
? 'Session expired \u2014 please re-authenticate with OpenAI'
|
||||
: `API error: ${response.status}`
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user