Skip to content

fix: track spawned profile ID to correctly attribute rate limit errors#1994

Open
octo-patch wants to merge 1 commit intoAndyMik90:developfrom
octo-patch:fix/rate-limit-profile-attribution
Open

fix: track spawned profile ID to correctly attribute rate limit errors#1994
octo-patch wants to merge 1 commit intoAndyMik90:developfrom
octo-patch:fix/rate-limit-profile-attribution

Conversation

@octo-patch
Copy link
Copy Markdown

@octo-patch octo-patch commented Apr 4, 2026

Fixes #1903

Problem

When a task process hits a rate limit, detectRateLimit() was called in handleProcessFailure() without passing the profileId of the profile that spawned the process. It fell back to profileManager.getActiveProfile().id, which may have changed since the process was spawned.

Concrete scenario: A user creates a Z.AI profile and switches to it. Tasks still running under "Primary"'s credentials hit Primary's rate limit. Because getActiveProfile() now returns Z.AI, the error gets attributed to Z.AI instead of Primary — showing the user an incorrect "Profile: Primary is rate limited" notification even while they believe they are using Z.AI only.

The AgentState.assignProfileToTask() mechanism already existed to track which profile was assigned to each task, but it was never called from spawnProcess().

Solution

  1. Changed setupProcessEnvironment() to return { env, profileId, profileName } so the caller knows which profile was selected by getBestAvailableProfileEnv().
  2. In spawnProcess(), record the profile assignment immediately after environment setup via this.state.assignProfileToTask().
  3. In handleProcessFailure(), look up the stored profile assignment and pass its profileId to detectRateLimit(), so rate limit events are correctly attributed to the profile that spawned the process.

Testing

The existing tests in agent-process.test.ts already mock getBestAvailableProfileEnv() to return { env: {}, profileId: 'default', profileName: 'Default', wasSwapped: false }, which is compatible with the updated return type — no test changes needed.

Summary by CodeRabbit

  • Refactor
    • Enhanced profile management by improving how task profiles are tracked and assigned throughout the agent process lifecycle.
    • Improved rate limit detection to operate with profile-specific context, enabling more granular throttling analysis.

When a task process hits a rate limit, detectRateLimit() was called
without a profileId and fell back to getActiveProfile(). If the user
switched profiles after the task started, the rate limit was attributed
to the wrong profile.

Fix by returning profileId from setupProcessEnvironment(), recording it
via state.assignProfileToTask() at spawn time, then passing it to
detectRateLimit() in handleProcessFailure().

Fixes AndyMik90#1903
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

📝 Walkthrough

Walkthrough

The PR fixes a bug where rate limit errors were incorrectly attributed to the inactive "Primary" profile instead of the active profile by enhancing profile tracking throughout the spawn and failure handling flow. Changes ensure spawned process tasks are assigned their correct profile and rate limit detection uses the proper profile context.

Changes

Cohort / File(s) Summary
Profile-Aware Process Spawning
apps/desktop/src/main/agent/agent-process.ts
Updated setupProcessEnvironment to return profile metadata (profileId, profileName), modified spawnProcess to assign the profile to tasks, and adjusted handleProcessFailure to pass profile identifier to rate-limit detection for accurate limit checking.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A profile mix-up caused quite the fright,
The Primary screamed, though Z.AI was right!
But now with correct scope, the limits align,
Each task knows its profile—a fix so divine! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: tracking spawned profile ID for correct rate-limit error attribution, which directly addresses the core problem in the changeset.
Linked Issues check ✅ Passed The pull request fully implements the solution to issue #1903 by: (1) returning profile info from setupProcessEnvironment(), (2) recording profile assignment in spawnProcess(), (3) passing profileId to detectRateLimit() in handleProcessFailure().
Out of Scope Changes check ✅ Passed All changes are directly within scope of fixing the rate-limit attribution issue; no unrelated modifications to other systems or functionality were introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the AgentProcessManager to track and attribute Claude profiles to specific tasks by modifying setupProcessEnvironment to return profile metadata and recording these assignments in the agent's state. Feedback indicates that the rate limit detection logic needs to be integrated into the primary spawnWorkerProcess execution path, as it is currently only present in a deprecated method. Additionally, the new task-to-profile assignments must be cleared upon process completion to prevent a memory leak.

Comment on lines +266 to +267
const profileAssignment = this.state.getTaskProfileAssignment(taskId);
const rateLimitDetection = detectRateLimit(allOutput, profileAssignment?.profileId);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The handleProcessFailure method is currently only invoked from the deprecated spawnProcess method. However, spawnWorkerProcess (line 838) is the primary execution path for autonomous AI tasks and it does not appear to utilize this rate limit detection and attribution logic. To fully address the issue described in the PR, the worker-based execution path should also be updated to track and attribute rate limits correctly.


const env = this.setupProcessEnvironment(extraEnv);
const { env, profileId: spawnedProfileId, profileName: spawnedProfileName } = this.setupProcessEnvironment(extraEnv);
this.state.assignProfileToTask(taskId, spawnedProfileId, spawnedProfileName, 'proactive');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

While calling assignProfileToTask here ensures correct attribution during failure, the assignment is never removed from the taskProfileAssignments map in AgentState. This will result in a memory leak as the map grows with every task execution. Please ensure that this.state.clearTaskProfileAssignment(taskId) is called in the process exit and error handlers (e.g., near lines 777 and 812).


const env = this.setupProcessEnvironment(extraEnv);
const { env, profileId: spawnedProfileId, profileName: spawnedProfileName } = this.setupProcessEnvironment(extraEnv);
this.state.assignProfileToTask(taskId, spawnedProfileId, spawnedProfileName, 'proactive');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The call to assignProfileToTask() was added to the deprecated spawnProcess method instead of the spawnWorkerProcess method used by production code, so profile assignments are not tracked.
Severity: MEDIUM

Suggested Fix

Move the assignProfileToTask() call from the deprecated spawnProcess method to the spawnWorkerProcess method. This will ensure that all production tasks have their associated profile ID correctly tracked for error handling.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: apps/desktop/src/main/agent/agent-process.ts#L554

Potential issue: The fix to track the profile ID for a spawned task was added to the
`spawnProcess` method. However, this method is deprecated and no longer used in
production. All production tasks are created via `spawnWorkerProcess`, which was not
modified to call `assignProfileToTask()`. As a result, when a task fails (e.g., due to a
rate limit), `handleProcessFailure` cannot retrieve the correct profile ID. The system
then falls back to the currently active profile, causing rate limit errors to be
misattributed if the user has switched profiles since the task began.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop/src/main/agent/agent-process.ts (1)

838-863: ⚠️ Potential issue | 🟠 Major

Add profile tracking to spawnWorkerProcess for rate limit attribution consistency.

The fix adds setupProcessEnvironment() and assignProfileToTask() to spawnProcess (line 553–554), but spawnWorkerProcess (lines 838–880) does not call these methods. Worker processes make SDK calls (via oauth-fetch, which operates in worker threads) and can trigger rate limits, but their exit handler (lines 889–911) lacks rate limit detection via handleProcessFailure().

Without profile tracking, if workers hit rate limits, those errors won't be attributed to the correct profile. Apply the same profile setup pattern to spawnWorkerProcess as spawnProcess for consistency and complete rate limit attribution.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/agent/agent-process.ts` around lines 838 - 863,
spawnWorkerProcess currently adds the process to state but does not call
setupProcessEnvironment() or assignProfileToTask(), so worker-thread SDK calls
won't be attributed to profiles; update spawnWorkerProcess to mirror
spawnProcess by invoking setupProcessEnvironment(taskId, executorConfig,
extraEnv, processType, projectId) before starting the worker and then call
assignProfileToTask(taskId, profile) (use the same profile object returned/used
by setupProcessEnvironment), and ensure the worker's exit/error handling routes
failures through handleProcessFailure(taskId, spawnId, error) so rate-limit
errors from worker threads are detected and attributed correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@apps/desktop/src/main/agent/agent-process.ts`:
- Around line 838-863: spawnWorkerProcess currently adds the process to state
but does not call setupProcessEnvironment() or assignProfileToTask(), so
worker-thread SDK calls won't be attributed to profiles; update
spawnWorkerProcess to mirror spawnProcess by invoking
setupProcessEnvironment(taskId, executorConfig, extraEnv, processType,
projectId) before starting the worker and then call assignProfileToTask(taskId,
profile) (use the same profile object returned/used by setupProcessEnvironment),
and ensure the worker's exit/error handling routes failures through
handleProcessFailure(taskId, spawnId, error) so rate-limit errors from worker
threads are detected and attributed correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7fb2bb16-c3fa-466c-b8b0-2cc2b68c54be

📥 Commits

Reviewing files that changed from the base of the PR and between cba7a02 and f165049.

📒 Files selected for processing (1)
  • apps/desktop/src/main/agent/agent-process.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect Rate Limit error for inactive "Primary" profile while using Z.AI API

2 participants