Skip to content
Merged
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
16 changes: 15 additions & 1 deletion packages/agent-core-v2/src/app/llmProtocol/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,18 @@ export class APIEmptyResponseError extends ChatProviderError {
}
}

const DETERMINISTIC_PROVIDER_VALIDATION_MESSAGE_PATTERNS = [
/unsupported media type for base64 image/,
/invalid data url for image/,
] as const;

function isDeterministicProviderValidationError(error: ChatProviderError): boolean {
const lowerMessage = error.message.toLowerCase();
return DETERMINISTIC_PROVIDER_VALIDATION_MESSAGE_PATTERNS.some((pattern) =>
pattern.test(lowerMessage),
);
}

export function isRetryableGenerateError(error: unknown): boolean {
if (error instanceof APIConnectionError || error instanceof APITimeoutError) {
return true;
Expand All @@ -149,7 +161,9 @@ export function isRetryableGenerateError(error: unknown): boolean {
if (error instanceof APIStatusError) {
return [408, 409, 429, 500, 502, 503, 504, 529].includes(error.statusCode);
}
return error instanceof ChatProviderError;
return (
error instanceof ChatProviderError && !isDeterministicProviderValidationError(error)
);
}

const NETWORK_RE = /network|connection|connect|disconnect|terminated/i;
Expand Down
9 changes: 9 additions & 0 deletions packages/agent-core-v2/test/app/llmProtocol/errors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ describe('isRetryableGenerateError', () => {
it('retries an unclassified provider error as a transient fallback', () => {
expect(isRetryableGenerateError(new ChatProviderError('upstream failure'))).toBe(true);
});

it.each([
['Invalid data URL for image: data:image/png;base64'],
[
'Unsupported media type for base64 image: image/avif, url: data:image/avif;base64,AAAA',
],
])('does not retry deterministic provider validation error: %s', (message) => {
expect(isRetryableGenerateError(new ChatProviderError(message))).toBe(false);
});
});

describe('error hierarchy instanceof checks', () => {
Expand Down
Loading