Skip to content

fix(ticket-sync): workspace awareness and auth error handling#524

Open
nethi wants to merge 4 commits intojonwiggins:mainfrom
nethi:fix/ticket-sync-gemini-auth-clean
Open

fix(ticket-sync): workspace awareness and auth error handling#524
nethi wants to merge 4 commits intojonwiggins:mainfrom
nethi:fix/ticket-sync-gemini-auth-clean

Conversation

@nethi
Copy link
Copy Markdown
Contributor

@nethi nethi commented Apr 27, 2026

Summary

Fixes ticket-sync workspace awareness and prevents reconcile loops caused by missing API keys (including Gemini).

Problem

  1. Ticket-sync workspace issues: Background jobs like ticket-sync couldn't find repos in non-default workspaces, causing tasks to always use claude-code agent regardless of repo configuration
  2. Reconcile loops: Missing API keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, etc.) were marked as retryable: true, causing tasks to retry indefinitely
  3. Missing Gemini auth handling: No error classification for missing GEMINI_API_KEY

Changes

Multi-workspace repo resolution (repo-service.ts)

  • Implemented 3-tier fallback in getRepoByUrl when no workspaceId specified:
    1. Default workspace
    2. NULL workspace_id
    3. Any workspace (for background jobs)
  • Added warning when multiple repos with same URL found across workspaces
  • Returns first match instead of throwing error (test-friendly)

Ticket-sync workspace awareness (ticket-sync-service.ts)

  • Changed configuredRepos query from selecting only { repoUrl } to full repo records
  • Pass workspaceId: repoConfig?.workspaceId to createTask for correct workspace assignment
  • Added warning when repo config not found
  • Log secret retrieval failures as warnings instead of silent swallowing

API key error handling (error-classifier.ts)

  • Changed retryable: trueretryable: false for all auth errors:
    • ANTHROPIC_API_KEY
    • OPENAI_API_KEY
    • OPENCLAW_API_KEY
    • COPILOT_GITHUB_TOKEN
    • OAuth token expired
    • Secret not found (generic)
  • Added new pattern: GEMINI_API_KEY with retryable: false
  • Improved "Secret not found" regex: /Secret not found: (\w+)|no (\w+) secret found/i

Testing

  • Verified background jobs can find repos in non-default workspaces
  • Confirmed missing API keys don't cause retry loops
  • Tested multi-workspace scenarios with duplicate repo URLs

Files Changed

  • apps/api/src/services/repo-service.ts - Multi-workspace fallback logic
  • apps/api/src/services/ticket-sync-service.ts - Workspace-aware task creation
  • packages/shared/src/error-classifier.ts - Auth error handling + Gemini support

Fixes ticket-sync workspace detection and prevents infinite retries on auth failures.

Ramesh Nethi and others added 4 commits April 27, 2026 18:01
Without a workspaceId, getRepoByUrl only looked in the 'default' slug
workspace. Background jobs like ticket sync have no workspace context, so
repos in user-created workspaces were never found — causing tasks to fall
back to claude-code regardless of the configured default agent type.

Added a three-tier fallback: default workspace → NULL workspace_id → any
workspace. Also surfaces secret retrieval failures in ticket sync as
warnings instead of swallowing them silently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove in-memory sort by createdAt in repo-service and ticket-sync
- Add warning when multiple repos found across workspaces
- Add warning when repo config not found in ticket-sync
- Pass workspaceId to createTask to ensure correct workspace assignment
- Remove unused desc imports

This ensures background jobs like ticket-sync work correctly with
multi-workspace setups without breaking test cases.
Copy link
Copy Markdown
Owner

@jonwiggins jonwiggins left a comment

Choose a reason for hiding this comment

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

The retryable-flip on auth errors is exactly the right call, and the new GEMINI_API_KEY pattern is welcome.

One correctness concern though: the new "any workspace" fallback in apps/api/src/services/repo-service.ts:144-160 affects every unscoped caller of getRepoByUrl, not just ticket-sync. The current callers that pass no workspaceId (or sometimes-null workspaceId) include:

  • task-service.ts:633
  • review-service.ts:94
  • subtask-service.ts:186
  • dependency-service.ts:218

In a multi-tenant deploy with the same repo URL configured across workspaces, this means any of these paths could now resolve to the wrong row. Single-workspace deploys are fine, but as a default this is a soft data-leak surface.

Could you gate the cross-workspace tier behind an explicit opt-in — e.g., getRepoByUrl(url, { workspaceId, allowAnyWorkspace: true }) — and only have ticket-sync pass it? The warning log helps detection but doesn't prevent the wrong resolution.

Also (small ask, not blocking): a regression test pinning retryable: false on the auth patterns in error-classifier.test.ts would make a future revert loud.

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.

2 participants