diff --git a/backend/helpers/jiraApi.js b/backend/helpers/jiraApi.js index 00bbc85..46ae6f7 100644 --- a/backend/helpers/jiraApi.js +++ b/backend/helpers/jiraApi.js @@ -276,8 +276,9 @@ function jiraDelete(urlPath, options) { * @param {string[]} [fields] - Jira field names to return */ async function getIssue(issueKey, fields) { - // Don't filter by project — issue keys are globally unique in Jira and - // tickets may belong to projects other than JIRA_PROJECT_KEY (e.g. AA_ADTRAN). + // Use JQL search to look up a single issue by key. + // Issue keys are globally unique in Jira — no project filter needed. + // Charter compliance: uses GET /rest/api/2/search with explicit field list. const jql = `key = "${issueKey}"`; const result = await searchIssues(jql, { fields: fields || DEFAULT_FIELDS, maxResults: 1, startAt: 0 }); if (result.ok && result.data.issues && result.data.issues.length > 0) { diff --git a/backend/routes/jiraTickets.js b/backend/routes/jiraTickets.js index d7e9816..3c23396 100644 --- a/backend/routes/jiraTickets.js +++ b/backend/routes/jiraTickets.js @@ -126,8 +126,24 @@ function createJiraTicketsRouter() { if (result.rateLimited) { return res.status(429).json({ error: 'Jira rate limit exceeded. Try again later.' }); } + // Build a meaningful error message from Jira's response + let errorMsg = result.status === 404 ? 'Issue not found in Jira.' : 'Jira API error.'; + if (result.body) { + try { + const parsed = typeof result.body === 'string' ? JSON.parse(result.body) : result.body; + if (parsed.errorMessages && parsed.errorMessages.length > 0) { + errorMsg = parsed.errorMessages.join('; '); + } else if (parsed.errors && Object.keys(parsed.errors).length > 0) { + errorMsg = Object.values(parsed.errors).join('; '); + } + } catch (_) { + if (typeof result.body === 'string' && result.body.length < 300) { + errorMsg = result.body; + } + } + } return res.status(result.status === 404 ? 404 : 502).json({ - error: result.status === 404 ? 'Issue not found in Jira.' : 'Jira API error.', + error: errorMsg, details: result.body }); } catch (err) {