Repository navigation
Feature/executor error retry - #493
Conversation
Add automatic retry capability when Claude SDK returns retryable errors like error_during_execution or error_max_turns. The retry mechanism: - Closes current client while preserving session_id - Creates new client with --resume option to restore session - Sends "Continue" message to resume execution - Supports up to 3 retry attempts before failing This improves task reliability by recovering from transient errors. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
error_max_turns indicates the task exceeded turn limits, which means the task is too complex. Retrying will likely hit the same limit again. Only error_during_execution (transient errors) should be retried. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Chinese and English translations for: - error_subtype_retry: Shown when retrying recoverable errors - error_subtype_max_retries: Shown when max retries reached Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use more descriptive retry message to prompt Claude to continue - Fix session_id handling in retry loop to use self.session_id - Prevent _create_and_connect_client from overwriting resume option - Add detailed logging for retry debugging Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RETRY_WITH_RESUME mechanism was using our internal session key
(task_id:bot_id format like "225172:100209") instead of the actual
Claude SDK session_id (UUID format like "024aee0c-019d-44d9-bce9-e91b96eadf9e").
Changes:
- _process_result_message now returns tuple ("RETRY_WITH_RESUME", actual_session_id)
where actual_session_id is msg.session_id from Claude SDK
- process_response propagates the tuple to the caller
- ClaudeCodeAgent extracts the UUID from the tuple and uses it for resume
This fixes the "Command failed with exit code 1" error after session resume
because Claude SDK's resume option requires the actual UUID, not our internal key.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR refactors the Claude code execution retry-with-resume flow to properly pass and utilize actual Claude session IDs. The response processor now returns a tuple containing the session ID instead of a plain string, allowing the agent to recreate the client with the correct session for resumption. Changes
Sequence Diagram(s)sequenceDiagram
participant Agent as Claude<br/>Code Agent
participant Processor as Response<br/>Processor
participant SDK as Claude<br/>SDK Client
Agent->>Processor: process_response(response, session_id)
alt Resume Required
Processor->>Processor: Detect retry condition<br/>Extract actual_session_id
Processor-->>Agent: ("RETRY_WITH_RESUME",<br/>actual_session_id)
Agent->>Agent: Extract tuple<br/>Set resume option
Agent->>SDK: _create_and_connect_client()<br/>with resume=actual_session_id
SDK-->>Agent: New client (resumed session)
Agent->>SDK: Send continue message<br/>to session_id
else Residual Interrupt
Processor-->>Agent: "RETRY_RESIDUAL"
Agent->>Agent: Queue message for resend
else Task Complete
Processor-->>Agent: TaskStatus result
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
executor/agents/claude_code/response_processor.py (1)
877-901:⚠️ Potential issue | 🟠 MajorGuard against passing internal session key to Claude SDK resume parameter.
If
msg.session_idisNone,actual_claude_session_idfalls back to thesession_idparameter, which can be an internal key format (e.g.,"task-123"or"123:456"). This is not a valid Claude UUID and would cause the resume to fail. Since a valid Claude session ID is required for proper resume, avoid returningRETRY_WITH_RESUMEwhenmsg.session_idisNone.Suggested fix
- # Get actual Claude session ID (UUID) for resume - # msg.session_id is the Claude UUID, session_id parameter is our internal key - actual_claude_session_id = msg.session_id or session_id + # Get actual Claude session ID (UUID) for resume + # msg.session_id is the Claude UUID, session_id parameter is our internal key + if not msg.session_id: + logger.warning( + f"No Claude session ID available for resume, " + f"cannot retry error subtype {msg.subtype}" + ) + # Fall through to fail the task since we can't resume without a valid session + else: + actual_claude_session_id = msg.session_id
🧹 Nitpick comments (2)
executor/agents/claude_code/response_processor.py (1)
269-269: Minor inconsistency: lowercasetuplevs importedTuple.Line 269 uses
tuple[bool, str](PEP 604 / Python 3.9+ syntax), while the rest of the file usesTuplefromtyping(line 5). This works fine on Python 3.9+ but is inconsistent. Consider unifying to one style.Use `Tuple` for consistency
-def _handle_user_message(msg: UserMessage, thinking_manager=None) -> tuple[bool, str]: +def _handle_user_message(msg: UserMessage, thinking_manager=None) -> Tuple[bool, str]:executor/agents/claude_code/claude_code_agent.py (1)
738-753: Staleresumeoption persists inself.optionsafter retry completes.After
self.options["resume"] = actual_claude_session_idon line 740, this key is never cleaned up when the retry loop exits (success or failure). While the current task lifecycle likely prevents reuse issues, this is defensive-coding debt:
_create_and_connect_client(line 805) guards withif "resume" not in self.options, so a staleresumekey would prevent loading a fresh saved session ID on any subsequent client creation for this agent instance.Consider cleaning up after the retry loop exits:
Clean up resume option after retry loop
# Continue loop to process response continue # Normal completion or non-retryable failure break + # Clean up retry-specific options + self.options.pop("resume", None) + if result is None:
* feat(executor): add retry mechanism for error_during_execution
Add automatic retry capability when Claude SDK returns retryable errors
like error_during_execution or error_max_turns. The retry mechanism:
- Closes current client while preserving session_id
- Creates new client with --resume option to restore session
- Sends "Continue" message to resume execution
- Supports up to 3 retry attempts before failing
This improves task reliability by recovering from transient errors.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(executor): remove error_max_turns from retryable errors
error_max_turns indicates the task exceeded turn limits, which means
the task is too complex. Retrying will likely hit the same limit again.
Only error_during_execution (transient errors) should be retried.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(frontend): add i18n translations for error retry mechanism
Add Chinese and English translations for:
- error_subtype_retry: Shown when retrying recoverable errors
- error_subtype_max_retries: Shown when max retries reached
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(executor): improve error retry mechanism
- Use more descriptive retry message to prompt Claude to continue
- Fix session_id handling in retry loop to use self.session_id
- Prevent _create_and_connect_client from overwriting resume option
- Add detailed logging for retry debugging
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(executor): use Claude SDK session_id (UUID) for RETRY_WITH_RESUME
The RETRY_WITH_RESUME mechanism was using our internal session key
(task_id:bot_id format like "225172:100209") instead of the actual
Claude SDK session_id (UUID format like "024aee0c-019d-44d9-bce9-e91b96eadf9e").
Changes:
- _process_result_message now returns tuple ("RETRY_WITH_RESUME", actual_session_id)
where actual_session_id is msg.session_id from Claude SDK
- process_response propagates the tuple to the caller
- ClaudeCodeAgent extracts the UUID from the tuple and uses it for resume
This fixes the "Command failed with exit code 1" error after session resume
because Claude SDK's resume option requires the actual UUID, not our internal key.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: yunpeng7 <yunpeng7@staff.weibo.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Feature/executor error retry (#493) See merge request weibo_rd/common/wecode/wegent!1413
Summary by CodeRabbit
Release Notes