-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix(vertex-anthropic): retry without prompt caching on Vertex SDK "path must be of type string. Received an instance of Array" error #7694
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
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 | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -83,20 +83,43 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple | |||||||||||||||
| * This ensures we stay under the 4-block limit while maintaining effective caching | ||||||||||||||||
| * for the most relevant context. | ||||||||||||||||
| */ | ||||||||||||||||
| const params: Anthropic.Messages.MessageCreateParamsStreaming = { | ||||||||||||||||
| // Build params with optional prompt caching | ||||||||||||||||
| const buildParams = (enableCache: boolean): Anthropic.Messages.MessageCreateParamsStreaming => ({ | ||||||||||||||||
| model: id, | ||||||||||||||||
| max_tokens: maxTokens ?? ANTHROPIC_DEFAULT_MAX_TOKENS, | ||||||||||||||||
| temperature, | ||||||||||||||||
| thinking, | ||||||||||||||||
| // Cache the system prompt if caching is enabled. | ||||||||||||||||
| system: supportsPromptCache | ||||||||||||||||
| system: enableCache | ||||||||||||||||
| ? [{ text: systemPrompt, type: "text" as const, cache_control: { type: "ephemeral" } }] | ||||||||||||||||
| : systemPrompt, | ||||||||||||||||
| messages: supportsPromptCache ? addCacheBreakpoints(messages) : messages, | ||||||||||||||||
| messages: enableCache ? addCacheBreakpoints(messages) : messages, | ||||||||||||||||
| stream: true, | ||||||||||||||||
| } | ||||||||||||||||
| }) | ||||||||||||||||
|
|
||||||||||||||||
| // Some environments (notably certain Vertex setups) have started throwing | ||||||||||||||||
| // TypeError("'path' argument must be of type string. Received an instance of Array") | ||||||||||||||||
| // when the SDK receives array-form system/content blocks. As a safe fallback, | ||||||||||||||||
| // retry without prompt caching if we detect this error. | ||||||||||||||||
| const isPathArrayError = (err: unknown) => | ||||||||||||||||
|
Contributor
Author
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. The
Suggested change
|
||||||||||||||||
| typeof (err as any)?.message === "string" && | ||||||||||||||||
| (err as any).message.includes("'path'") && | ||||||||||||||||
| (err as any).message.includes("type string") && | ||||||||||||||||
| (err as any).message.includes("Array") | ||||||||||||||||
|
|
||||||||||||||||
| const stream = await this.client.messages.create(params) | ||||||||||||||||
| let stream: AsyncIterable<any> | ||||||||||||||||
| try { | ||||||||||||||||
| stream = await this.client.messages.create(buildParams(!!supportsPromptCache)) | ||||||||||||||||
| } catch (err) { | ||||||||||||||||
| if (supportsPromptCache && isPathArrayError(err)) { | ||||||||||||||||
| console.warn( | ||||||||||||||||
|
Contributor
Author
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. Consider including the model ID in the warning message for better debugging context:
Suggested change
|
||||||||||||||||
| "Roo Code <Vertex/Anthropic>: Retry without prompt caching due to path/Array error:", | ||||||||||||||||
| (err as any).message, | ||||||||||||||||
| ) | ||||||||||||||||
| stream = await this.client.messages.create(buildParams(false)) | ||||||||||||||||
| } else { | ||||||||||||||||
| throw err | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| for await (const chunk of stream) { | ||||||||||||||||
| switch (chunk.type) { | ||||||||||||||||
|
|
@@ -185,35 +208,52 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple | |||||||||||||||
| reasoning: thinking, | ||||||||||||||||
| } = this.getModel() | ||||||||||||||||
|
|
||||||||||||||||
| const params: Anthropic.Messages.MessageCreateParamsNonStreaming = { | ||||||||||||||||
| const buildParams = (enableCache: boolean): Anthropic.Messages.MessageCreateParamsNonStreaming => ({ | ||||||||||||||||
| model: id, | ||||||||||||||||
| max_tokens: maxTokens, | ||||||||||||||||
| temperature, | ||||||||||||||||
| thinking, | ||||||||||||||||
| messages: [ | ||||||||||||||||
| { | ||||||||||||||||
| role: "user", | ||||||||||||||||
| content: supportsPromptCache | ||||||||||||||||
| content: enableCache | ||||||||||||||||
| ? [{ type: "text" as const, text: prompt, cache_control: { type: "ephemeral" } }] | ||||||||||||||||
| : prompt, | ||||||||||||||||
| }, | ||||||||||||||||
| ], | ||||||||||||||||
| stream: false, | ||||||||||||||||
| }) | ||||||||||||||||
|
|
||||||||||||||||
| const isPathArrayError = (err: unknown) => | ||||||||||||||||
|
Contributor
Author
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. Same duplication of |
||||||||||||||||
| typeof (err as any)?.message === "string" && | ||||||||||||||||
| (err as any).message.includes("'path'") && | ||||||||||||||||
| (err as any).message.includes("type string") && | ||||||||||||||||
| (err as any).message.includes("Array") | ||||||||||||||||
|
|
||||||||||||||||
| let response: Anthropic.Messages.Message | ||||||||||||||||
| try { | ||||||||||||||||
| response = await this.client.messages.create(buildParams(!!supportsPromptCache)) | ||||||||||||||||
| } catch (err) { | ||||||||||||||||
| if (supportsPromptCache && isPathArrayError(err)) { | ||||||||||||||||
| console.warn( | ||||||||||||||||
|
Contributor
Author
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. Similar to the streaming case, consider including the model ID in this warning:
Suggested change
|
||||||||||||||||
| "Roo Code <Vertex/Anthropic>: Non-streaming retry without prompt caching due to path/Array error:", | ||||||||||||||||
| (err as any).message, | ||||||||||||||||
| ) | ||||||||||||||||
| response = await this.client.messages.create(buildParams(false)) | ||||||||||||||||
| } else { | ||||||||||||||||
| throw err | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| const response = await this.client.messages.create(params) | ||||||||||||||||
| const content = response.content[0] | ||||||||||||||||
|
|
||||||||||||||||
| if (content.type === "text") { | ||||||||||||||||
| return content.text | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| return "" | ||||||||||||||||
| } catch (error) { | ||||||||||||||||
| if (error instanceof Error) { | ||||||||||||||||
| throw new Error(`Vertex completion error: ${error.message}`) | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| throw 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.
Consider extracting the isPathArrayError function into a shared helper to avoid duplicating this logic in both createMessage and completePrompt.
This comment was generated because it violated a code review rule: irule_tTqpIuNs8DV0QFGj.