mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
fix: prevent infinite retry loop for images exceeding 5MB
- Change MAX_IMAGE_BYTES from 6MB to 5MB to match Anthropic API limit - Add isImageSizeError() to detect image size errors from API - Handle image size errors with user-friendly message instead of retry - Prevent failover for image size errors (not retriable) Fixes #2271
This commit is contained in:
@@ -23,6 +23,7 @@ export {
|
||||
isFailoverAssistantError,
|
||||
isFailoverErrorMessage,
|
||||
isImageDimensionErrorMessage,
|
||||
isImageSizeError,
|
||||
isOverloadedErrorMessage,
|
||||
isRawApiErrorPayload,
|
||||
isRateLimitAssistantError,
|
||||
|
||||
@@ -467,6 +467,12 @@ export function isImageDimensionErrorMessage(raw: string): boolean {
|
||||
return Boolean(parseImageDimensionError(raw));
|
||||
}
|
||||
|
||||
export function isImageSizeError(errorMessage?: string): boolean {
|
||||
if (!errorMessage) return false;
|
||||
const lower = errorMessage.toLowerCase();
|
||||
return lower.includes("image exceeds") && lower.includes("mb");
|
||||
}
|
||||
|
||||
export function isCloudCodeAssistFormatError(raw: string): boolean {
|
||||
return !isImageDimensionErrorMessage(raw) && matchesErrorPatterns(raw, ERROR_PATTERNS.format);
|
||||
}
|
||||
@@ -478,6 +484,7 @@ export function isAuthAssistantError(msg: AssistantMessage | undefined): boolean
|
||||
|
||||
export function classifyFailoverReason(raw: string): FailoverReason | null {
|
||||
if (isImageDimensionErrorMessage(raw)) return null;
|
||||
if (isImageSizeError(raw)) return null;
|
||||
if (isRateLimitErrorMessage(raw)) return "rate_limit";
|
||||
if (isOverloadedErrorMessage(raw)) return "rate_limit";
|
||||
if (isCloudCodeAssistFormatError(raw)) return "format";
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
isContextOverflowError,
|
||||
isFailoverAssistantError,
|
||||
isFailoverErrorMessage,
|
||||
isImageSizeError,
|
||||
parseImageDimensionError,
|
||||
isRateLimitAssistantError,
|
||||
isTimeoutErrorMessage,
|
||||
@@ -440,6 +441,29 @@ export async function runEmbeddedPiAgent(
|
||||
},
|
||||
};
|
||||
}
|
||||
// Handle image size errors with a user-friendly message (no retry needed)
|
||||
if (isImageSizeError(errorText)) {
|
||||
return {
|
||||
payloads: [
|
||||
{
|
||||
text:
|
||||
"Image too large for the model (max 5MB). " +
|
||||
"Please compress or resize the image and try again.",
|
||||
isError: true,
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
durationMs: Date.now() - started,
|
||||
agentMeta: {
|
||||
sessionId: sessionIdUsed,
|
||||
provider,
|
||||
model: model.id,
|
||||
},
|
||||
systemPromptReport: attempt.systemPromptReport,
|
||||
error: { kind: "image_size", message: errorText },
|
||||
},
|
||||
};
|
||||
}
|
||||
const promptFailoverReason = classifyFailoverReason(errorText);
|
||||
if (promptFailoverReason && promptFailoverReason !== "timeout" && lastProfileId) {
|
||||
await markAuthProfileFailure({
|
||||
|
||||
@@ -20,7 +20,7 @@ export type EmbeddedPiRunMeta = {
|
||||
aborted?: boolean;
|
||||
systemPromptReport?: SessionSystemPromptReport;
|
||||
error?: {
|
||||
kind: "context_overflow" | "compaction_failure" | "role_ordering";
|
||||
kind: "context_overflow" | "compaction_failure" | "role_ordering" | "image_size";
|
||||
message: string;
|
||||
};
|
||||
/** Stop reason for the agent run (e.g., "completed", "tool_calls"). */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const MAX_IMAGE_BYTES = 6 * 1024 * 1024; // 6MB
|
||||
export const MAX_IMAGE_BYTES = 5 * 1024 * 1024; // 5MB (Anthropic API limit)
|
||||
export const MAX_AUDIO_BYTES = 16 * 1024 * 1024; // 16MB
|
||||
export const MAX_VIDEO_BYTES = 16 * 1024 * 1024; // 16MB
|
||||
export const MAX_DOCUMENT_BYTES = 100 * 1024 * 1024; // 100MB
|
||||
|
||||
Reference in New Issue
Block a user