Conversation
There was a problem hiding this comment.
Pull request overview
This PR aims to fix Cloud Code Assist API errors (429 RESOURCE_EXHAUSTED and 400 INVALID_ARGUMENT) by enhancing error detection and adding tool call ID sanitization to ensure proper failover when these errors occur.
Key changes:
- Enhanced rate limit and authentication error detection with Cloud Code Assist specific patterns
- Added tool call ID sanitization to replace invalid characters with valid ones
- Integrated Cloud Code Assist format error detection into the failover system
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| src/config/paths.ts | Adds legacy exports for Clawdis → Clawdbot rebrand (unrelated to PR purpose) |
| src/agents/pi-embedded-helpers.ts | Enhances error detection patterns, adds tool call ID sanitization, and integrates sanitization into message processing |
| src/agents/pi-embedded-runner.ts | Adds Cloud Code Assist format error detection to retry/failover logic with appropriate logging |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const trimmedInvalidStartChars = cloudCodeAssistPatternReplacement.replace( | ||
| /^[^a-zA-Z0-9_-]+/, | ||
| "", | ||
| ); | ||
|
|
||
| return trimmedInvalidStartChars.length > 0 | ||
| ? trimmedInvalidStartChars |
There was a problem hiding this comment.
The second regex replacement on lines 464-466 is redundant and will never match anything. After line 463 replaces all invalid characters with underscores, the string can only contain valid characters [a-zA-Z0-9_-], so the pattern ^[^a-zA-Z0-9_-]+ will never find any leading invalid characters to remove. Consider removing this redundant operation.
| const trimmedInvalidStartChars = cloudCodeAssistPatternReplacement.replace( | |
| /^[^a-zA-Z0-9_-]+/, | |
| "", | |
| ); | |
| return trimmedInvalidStartChars.length > 0 | |
| ? trimmedInvalidStartChars | |
| return cloudCodeAssistPatternReplacement.length > 0 | |
| ? cloudCodeAssistPatternReplacement |
| value.includes("resource has been exhausted") || | ||
| value.includes("invalid_request_error") || | ||
| value.includes("string should match pattern") || | ||
| value.includes("tool_use_id") || |
There was a problem hiding this comment.
There's an inconsistency in pattern matching: line 288 checks for "tool_use_id" (with underscore) while line 300 checks for "tool_use.id" (with dot). These are different patterns that won't match the same error messages. Based on the specific pattern in line 301 ("messages.1.content.1.tool_use.id"), the correct pattern appears to be with dots, not underscores. Verify which pattern is actually returned by Cloud Code Assist API and ensure consistency across both functions.
| value.includes("tool_use_id") || | |
| value.includes("tool_use.id") || |
| const sanitizedContent = await Promise.all( | ||
| filteredContent.map(async (block) => { | ||
| if ( | ||
| block && | ||
| typeof block === "object" && | ||
| (block as { type?: unknown }).type === "functionCall" && | ||
| (block as { id?: unknown }).id | ||
| ) { | ||
| const functionBlock = block as { type: string; id: string }; | ||
| return { | ||
| ...functionBlock, | ||
| id: sanitizeToolCallId(functionBlock.id), | ||
| }; | ||
| } | ||
| return block; | ||
| }), | ||
| ); |
There was a problem hiding this comment.
The Promise.all with async map function on lines 123-139 is unnecessary since sanitizeToolCallId is a synchronous function. The code can be simplified by using a regular map() instead of await Promise.all(filteredContent.map(async ...)), which would improve performance by avoiding unnecessary promise wrapping for synchronous operations.
| const sanitizedContent = await Promise.all( | |
| filteredContent.map(async (block) => { | |
| if ( | |
| block && | |
| typeof block === "object" && | |
| (block as { type?: unknown }).type === "functionCall" && | |
| (block as { id?: unknown }).id | |
| ) { | |
| const functionBlock = block as { type: string; id: string }; | |
| return { | |
| ...functionBlock, | |
| id: sanitizeToolCallId(functionBlock.id), | |
| }; | |
| } | |
| return block; | |
| }), | |
| ); | |
| const sanitizedContent = filteredContent.map((block) => { | |
| if ( | |
| block && | |
| typeof block === "object" && | |
| (block as { type?: unknown }).type === "functionCall" && | |
| (block as { id?: unknown }).id | |
| ) { | |
| const functionBlock = block as { type: string; id: string }; | |
| return { | |
| ...functionBlock, | |
| id: sanitizeToolCallId(functionBlock.id), | |
| }; | |
| } | |
| return block; | |
| }); |
| @@ -248,16 +280,38 @@ export function isAuthErrorMessage(raw: string): boolean { | |||
| value.includes("unauthorized") || | |||
| value.includes("forbidden") || | |||
| value.includes("access denied") || | |||
| value.includes("expired") || | |||
| value.includes("token has expired") || | |||
| value.includes("resource has been exhausted") || | |||
There was a problem hiding this comment.
The error pattern "resource has been exhausted" is duplicated in both isRateLimitErrorMessage (line 265) and isAuthErrorMessage (line 285). This creates ambiguity in error classification. Since this error typically indicates quota/rate limit exhaustion rather than authentication failure, it should only be included in isRateLimitErrorMessage.
| value.includes("resource has been exhausted") || |
| value.includes("invalid_request_error") || | ||
| value.includes("string should match pattern") || | ||
| value.includes("tool_use_id") || |
There was a problem hiding this comment.
Adding format validation error patterns ("invalid_request_error", "string should match pattern", "tool_use_id") to isAuthErrorMessage is semantically incorrect. These patterns indicate request format issues, not authentication failures. This conflates two distinct error categories and may cause incorrect error handling. Consider removing these patterns from this function since they're already handled by isCloudCodeAssistFormatError.
| value.includes("invalid_request_error") || | |
| value.includes("string should match pattern") || | |
| value.includes("tool_use_id") || |
| return ( | ||
| isAuthErrorMessage(errorMessage) || | ||
| isCloudCodeAssistFormatError(errorMessage) | ||
| ); |
There was a problem hiding this comment.
The isAuthAssistantError function now treats Cloud Code Assist format errors as authentication errors by including isCloudCodeAssistFormatError in its logic. This is semantically incorrect - format validation errors are distinct from authentication failures. While the failover behavior might be similar, conflating these error types reduces code clarity and makes debugging more difficult. Consider separating format error handling from authentication error handling at the calling sites instead.
| return ( | |
| isAuthErrorMessage(errorMessage) || | |
| isCloudCodeAssistFormatError(errorMessage) | |
| ); | |
| return isAuthErrorMessage(errorMessage); |
|
please retest this once #543 landed |
|
Will do
I did test 5 PR but one of them jammed lol
So from tomorrow I’ll just test one PR
This one was annoying me a lot today because I burned my credits and had to wait the 5hrs limit lol
Get Outlook for iOS<https://aka.ms/o0ukef>
…________________________________
From: Peter Steinberger ***@***.***>
Sent: Thursday, January 8, 2026 7:08:58 PM
To: clawdbot/clawdbot ***@***.***>
Cc: Jefferson Nunn ***@***.***>; Author ***@***.***>
Subject: Re: [clawdbot/clawdbot] Fix Cloud Code Assist API errors (429/400) (PR #544)
[https://avatars.githubusercontent.com/u/58493?s=20&v=4]steipete left a comment (openclaw/openclaw#544)<#544 (comment)>
please retest this once #543<#543> landed
—
Reply to this email directly, view it on GitHub<#544 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AVHICTML3F7VDN4B63TRKPD4F35SVAVCNFSM6AAAAACREBYVPKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTOMRWGYZDKOBRG4>.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
- Add sanitizeToolCallId() to fix Cloud Code Assist tool call ID validation - Apply sanitization in sanitizeSessionMessagesImages() for toolResult and assistant messages - Add legacy CONFIG_PATH_CLAWDIS and STATE_DIR_CLAWDIS exports for backward compatibility - Resolves Cloud Code Assist rejection of invalid tool call IDs with pipe characters - Fixes missing session export functions that were blocking system startup Addresses Cloud Code Assist API 400 errors from invalid tool call IDs like 'call_abc123|item_456'
- Enhanced rate limit detection for Cloud Code Assist quota exhaustion - Added tool call ID sanitization to fix invalid request format errors - Integrated Cloud Code Assist format error detection into failover system - Added comprehensive error pattern matching for Cloud Code Assist APIs Fixes #cloud-code-assist-api-errors
|
Very welcome
Hope to be back on it tomorrow.
Get Outlook for iOS<https://aka.ms/o0ukef>
…________________________________
From: Peter Steinberger ***@***.***>
Sent: Friday, January 9, 2026 6:14:46 PM
To: clawdbot/clawdbot ***@***.***>
Cc: Jefferson Nunn ***@***.***>; Mention ***@***.***>
Subject: Re: [clawdbot/clawdbot] Fix Cloud Code Assist API errors (429/400) (PR #544)
[https://avatars.githubusercontent.com/u/58493?s=20&v=4]steipete left a comment (openclaw/openclaw#544)<#544 (comment)>
Landed via temp rebase onto main.
* Gate: pnpm lint && pnpm build && pnpm test
* Land commit: 251ed83<251ed83>
* Merge commit: 08015fb<08015fb>
Thanks @jeffersonwarrior<https://github.com/jeffersonwarrior>!
—
Reply to this email directly, view it on GitHub<#544 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AVHICTOXPQNS4RANAEUQHVT4GA77NAVCNFSM6AAAAACREBYVPKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTOMZRGEYDMNJSGE>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
…assist-api-errors Fix Cloud Code Assist API errors (429/400)
…assist-api-errors Fix Cloud Code Assist API errors (429/400)
Summary
This PR fixes critical Cloud Code Assist API errors that were causing user-facing failures:
Changes Made
Enhanced Rate Limit Detection (
src/agents/pi-embedded-helpers.ts)"resource has been exhausted","quota exceeded","resource_exhausted"isRateLimitErrorMessage()to handle Cloud Code Assist quota errorsTool Call ID Sanitization (
src/agents/pi-embedded-helpers.ts)sanitizeToolCallId()with comprehensive validation and pattern matchingisValidCloudCodeAssistToolId()for proper Cloud Code Assist format validation (^[a-zA-Z0-9_-]+$)isCloudCodeAssistFormatError()for specific Cloud Code Assist error detectionIntegrated Failover System (
src/agents/pi-embedded-runner.ts)Files Changed
src/agents/pi-embedded-helpers.ts- Enhanced error detection and tool call sanitizationsrc/agents/pi-embedded-runner.ts- Integrated Cloud Code Assist error handling into failover systemTesting
Impact
This makes the system production-ready for Cloud Code Assist integration with robust error handling.
Fixes: Cloud Code Assist API integration errors