fix(tools): add Atlassian error extractor to all Jira, JSM, and Confluence tools#4085
Conversation
…uence tools Wire up the existing `atlassian-errors` error extractor to all 95 Atlassian tool configs so the executor surfaces meaningful error messages instead of generic status codes. Also fix the extractor itself to handle all three Atlassian error response formats: `errorMessage` (JSM), `errorMessages` array (Jira), and `message` (Confluence). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Expands Reviewed by Cursor Bugbot for commit 4a1a84e. Configure here. |
Greptile SummaryThis PR wires The improvements to the extractor logic are correct for tools that call Atlassian APIs directly. For tools routed through internal Next.js proxy handlers ( Confidence Score: 4/5Safe to merge for direct-API Atlassian tools; the extractor bypass for proxy-routed tools (JSM, most Confluence) is an unresolved P1 from prior review threads that means those paths still surface generic status-code errors. All new findings from this review are P2. However, two P1 findings from prior review threads remain unaddressed: the apps/sim/tools/error-extractors.ts — RFC 7807 detail-without-title fallthrough; also see prior thread on data.error proxy format not being matched. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Tool Request Fails] --> B{Has errorExtractor?}
B -->|Yes: atlassian-errors| C{Direct Atlassian API?}
B -->|No| D[Try all extractors in order]
C -->|Yes - Jira retrieve etc.| E[Raw Atlassian error body]
C -->|No - via /api/tools/jsm or /api/tools/confluence| F[Proxy wraps as data.error string]
E --> G{Check errorMessage}
G -->|found| H[Return errorMessage]
G -->|not found| I{Check errorMessages array}
I -->|found| J[Return joined messages]
I -->|not found| K{Check errors array - RFC 7807}
K -->|found with title| L[Return title: detail]
K -->|found, no title but has detail| M[⚠️ Silent fallthrough - no return]
K -->|not found| N{Check errors object - field-level}
N -->|found| O[Return field: msg pairs]
N -->|not found| P{Check message}
P -->|found| Q[Return message]
P -->|not found| R[Return 'Request failed with status X']
F --> S{atlassian-errors checks data.error?}
S -->|No - not handled| R
M --> P
Reviews (1): Last reviewed commit: "fix(tools): handle all Atlassian error f..." | Re-trigger Greptile |
Add RFC 7807 errors[].title format (Confluence v2, Forms/ProForma API) and Jira field-level errors object to the atlassian-errors extractor.
| provider: 'jira', | ||
| }, | ||
|
|
||
| errorExtractor: 'atlassian-errors', |
There was a problem hiding this comment.
atlassian-errors extractor is bypassed for all internal-route tools
All 24 JSM tools route through /api/tools/jsm/.... When the Atlassian API call fails, these routes extract the Atlassian message and return it wrapped as { error: "JSM API error: <message>" } (see route.ts:parseJsmErrorMessage). The atlassian-errors extractor only checks errorMessage, errorMessages[], and message — none of which is error — so it returns undefined and the executor surfaces "Request failed with status X".
Before this PR, the absence of errorExtractor caused the executor to try all extractors in fallback order. The nested-error-object extractor matched data.error and correctly returned the human-readable string. This PR's deterministic mode skips all fallbacks, so meaningful error text is now silently dropped.
The same regression affects Confluence tools that use /api/tools/confluence/... routes (e.g., search/route.ts:70 returns { error: errorMessage }), and Jira tools write.ts, update.ts, and add_attachment.ts.
The fix needs to either: (a) update internal API routes to forward the Atlassian error body unchanged instead of re-wrapping it, (b) use a composite extractor that also checks data.error, or (c) omit errorExtractor on the internal-route tools to restore fallback behavior.
| examples: ['Jira', 'Jira Service Management', 'Confluence', 'JSM Forms/ProForma'], | ||
| extract: (errorInfo) => { | ||
| // JSM Service Desk: singular errorMessage string | ||
| if (errorInfo?.data?.errorMessage) { | ||
| return errorInfo.data.errorMessage | ||
| } | ||
| // Jira Platform: errorMessages array | ||
| if ( | ||
| Array.isArray(errorInfo?.data?.errorMessages) && | ||
| errorInfo.data.errorMessages.length > 0 | ||
| ) { | ||
| return errorInfo.data.errorMessages.join(', ') | ||
| } | ||
| // Confluence v2 / Forms API: RFC 7807 errors array with title/detail | ||
| if (Array.isArray(errorInfo?.data?.errors) && errorInfo.data.errors.length > 0) { |
There was a problem hiding this comment.
Use
ErrorExtractorId constant for type safety
All 95 Atlassian tool files use the string literal 'atlassian-errors' rather than the ErrorExtractorId.ATLASSIAN_ERRORS constant exported from this file. Other integrations (e.g., Telegram tools) consistently use ErrorExtractorId.TELEGRAM_DESCRIPTION. A typo in a string literal would silently fall back to the generic "Request failed with status X" message, whereas the constant provides compile-time safety.
| if (Array.isArray(errorInfo?.data?.errors) && errorInfo.data.errors.length > 0) { | ||
| const err = errorInfo.data.errors[0] | ||
| if (err?.title) { | ||
| return err.detail ? `${err.title}: ${err.detail}` : err.title | ||
| } | ||
| } |
There was a problem hiding this comment.
RFC 7807
errors array silently drops detail when title is absent
If errors is a non-empty array but the first entry carries detail without a title (permissible under RFC 7807, which makes title optional), the inner if (err?.title) block is skipped without returning. Because errors IS an array, the field-level object check (!Array.isArray) is also skipped, so the extractor falls through to data.message and ultimately returns undefined. The detail text is silently lost and the executor surfaces "Request failed with status X" instead.
| if (Array.isArray(errorInfo?.data?.errors) && errorInfo.data.errors.length > 0) { | |
| const err = errorInfo.data.errors[0] | |
| if (err?.title) { | |
| return err.detail ? `${err.title}: ${err.detail}` : err.title | |
| } | |
| } | |
| if (Array.isArray(errorInfo?.data?.errors) && errorInfo.data.errors.length > 0) { | |
| const err = errorInfo.data.errors[0] | |
| if (err?.title) { | |
| return err.detail ? `${err.title}: ${err.detail}` : err.title | |
| } | |
| if (err?.detail) { | |
| return err.detail | |
| } | |
| } |
…uence tools (#4085) * fix(tools): add Atlassian error extractor to all Jira, JSM, and Confluence tools Wire up the existing `atlassian-errors` error extractor to all 95 Atlassian tool configs so the executor surfaces meaningful error messages instead of generic status codes. Also fix the extractor itself to handle all three Atlassian error response formats: `errorMessage` (JSM), `errorMessages` array (Jira), and `message` (Confluence). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore(tools): lint formatting fix for error extractor * fix(tools): handle all Atlassian error formats in error extractor Add RFC 7807 errors[].title format (Confluence v2, Forms/ProForma API) and Jira field-level errors object to the atlassian-errors extractor. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
atlassian-errorserror extractor to all 95 Atlassian tool configs (25 Jira, 24 JSM, 46 Confluence) so the executor surfaces meaningful error messages instead of generic "Request failed with status X"atlassian-errorsextractor itself to handle all three Atlassian error response formats:errorMessage(JSM),errorMessagesarray (Jira), andmessage(Confluence)Test plan