Skip to content

Commit ccd68ac

Browse files
committed
fix(vertex-anthropic): retry without prompt caching when Vertex SDK throws "path must be of type string. Received an instance of Array"
1 parent 90e7d09 commit ccd68ac

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

src/api/providers/anthropic-vertex.ts

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,43 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple
8383
* This ensures we stay under the 4-block limit while maintaining effective caching
8484
* for the most relevant context.
8585
*/
86-
const params: Anthropic.Messages.MessageCreateParamsStreaming = {
86+
// Build params with optional prompt caching
87+
const buildParams = (enableCache: boolean): Anthropic.Messages.MessageCreateParamsStreaming => ({
8788
model: id,
8889
max_tokens: maxTokens ?? ANTHROPIC_DEFAULT_MAX_TOKENS,
8990
temperature,
9091
thinking,
91-
// Cache the system prompt if caching is enabled.
92-
system: supportsPromptCache
92+
system: enableCache
9393
? [{ text: systemPrompt, type: "text" as const, cache_control: { type: "ephemeral" } }]
9494
: systemPrompt,
95-
messages: supportsPromptCache ? addCacheBreakpoints(messages) : messages,
95+
messages: enableCache ? addCacheBreakpoints(messages) : messages,
9696
stream: true,
97-
}
97+
})
98+
99+
// Some environments (notably certain Vertex setups) have started throwing
100+
// TypeError("'path' argument must be of type string. Received an instance of Array")
101+
// when the SDK receives array-form system/content blocks. As a safe fallback,
102+
// retry without prompt caching if we detect this error.
103+
const isPathArrayError = (err: unknown) =>
104+
typeof (err as any)?.message === "string" &&
105+
(err as any).message.includes("'path'") &&
106+
(err as any).message.includes("type string") &&
107+
(err as any).message.includes("Array")
98108

99-
const stream = await this.client.messages.create(params)
109+
let stream: AsyncIterable<any>
110+
try {
111+
stream = await this.client.messages.create(buildParams(!!supportsPromptCache))
112+
} catch (err) {
113+
if (supportsPromptCache && isPathArrayError(err)) {
114+
console.warn(
115+
"Roo Code <Vertex/Anthropic>: Retry without prompt caching due to path/Array error:",
116+
(err as any).message,
117+
)
118+
stream = await this.client.messages.create(buildParams(false))
119+
} else {
120+
throw err
121+
}
122+
}
100123

101124
for await (const chunk of stream) {
102125
switch (chunk.type) {
@@ -185,35 +208,52 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple
185208
reasoning: thinking,
186209
} = this.getModel()
187210

188-
const params: Anthropic.Messages.MessageCreateParamsNonStreaming = {
211+
const buildParams = (enableCache: boolean): Anthropic.Messages.MessageCreateParamsNonStreaming => ({
189212
model: id,
190213
max_tokens: maxTokens,
191214
temperature,
192215
thinking,
193216
messages: [
194217
{
195218
role: "user",
196-
content: supportsPromptCache
219+
content: enableCache
197220
? [{ type: "text" as const, text: prompt, cache_control: { type: "ephemeral" } }]
198221
: prompt,
199222
},
200223
],
201224
stream: false,
225+
})
226+
227+
const isPathArrayError = (err: unknown) =>
228+
typeof (err as any)?.message === "string" &&
229+
(err as any).message.includes("'path'") &&
230+
(err as any).message.includes("type string") &&
231+
(err as any).message.includes("Array")
232+
233+
let response: Anthropic.Messages.Message
234+
try {
235+
response = await this.client.messages.create(buildParams(!!supportsPromptCache))
236+
} catch (err) {
237+
if (supportsPromptCache && isPathArrayError(err)) {
238+
console.warn(
239+
"Roo Code <Vertex/Anthropic>: Non-streaming retry without prompt caching due to path/Array error:",
240+
(err as any).message,
241+
)
242+
response = await this.client.messages.create(buildParams(false))
243+
} else {
244+
throw err
245+
}
202246
}
203247

204-
const response = await this.client.messages.create(params)
205248
const content = response.content[0]
206-
207249
if (content.type === "text") {
208250
return content.text
209251
}
210-
211252
return ""
212253
} catch (error) {
213254
if (error instanceof Error) {
214255
throw new Error(`Vertex completion error: ${error.message}`)
215256
}
216-
217257
throw error
218258
}
219259
}

0 commit comments

Comments
 (0)