{"record":{"id":"0de900b19c3cf343","repo":"FlowiseAI/Flowise","slug":"jira-api-error-response-status-response-stat","errorCode":null,"errorMessage":"Jira API Error ${response.status}: ${response.statusText} - ${errorText}","messagePattern":"Jira API Error (.+?): (.+?) - (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/tools/Jira/core.ts","lineNumber":202,"sourceCode":"        const headers = {\n            Authorization: authHeader,\n            'Content-Type': 'application/json',\n            Accept: 'application/json',\n            ...this.headers\n        }\n\n        const fetchOptions: any = {\n            method,\n            headers,\n            body: body ? JSON.stringify(body) : undefined\n        }\n\n        const agentOptions = this.authConfig?.sslCertificate ? { ca: this.authConfig.sslCertificate } : undefined\n        const response = await secureFetch(url, fetchOptions, 5, agentOptions)\n\n        if (!response.ok) {\n            const errorText = await response.text()\n            throw new Error(`Jira API Error ${response.status}: ${response.statusText} - ${errorText}`)\n        }\n\n        const data = await response.text()\n        return data + TOOL_ARGS_PREFIX + JSON.stringify(params)\n    }\n}\n\n// Issue Tools\nclass ListIssuesTool extends BaseJiraTool {\n    defaultParams: any\n\n    constructor(args: any) {\n        const toolInput = {\n            name: 'list_issues',\n            description: 'List issues from Jira using JQL query',\n            schema: ListIssuesSchema,\n            baseUrl: '',\n            method: 'GET',","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/tools/Jira/core.ts#L184-L220","documentation":"Thrown by BaseJiraTool.makeJiraRequest when the Jira REST API responds with a non-2xx status. The request goes through secureFetch (with optional SSL CA, 5 retries) to <jiraHost>/rest/api/<2|3>/<endpoint>; on response.ok===false the body is read and the status code, status text, and raw body are fused. The apiVersion is derived from authType (bearer→v2 for Server/DC, basic→v3 for Cloud), so a version/auth mismatch surfaces here as 404 or 401.","triggerScenarios":"401 from an expired/revoked token; 403 from insufficient project permissions; 404 from a wrong endpoint path, a jiraHost that points at the wrong product, or using v3 endpoints on a Server/DC install; 400 from a malformed JQL query (list_issues) or invalid issueTypeId; 5xx during Jira outage. SSL mismatches produce fetch-level errors before this throw, but a self-signed cert not matching the supplied CA can yield a 4xx via a proxy.","commonSituations":"Using Cloud credentials (Basic/v3) against a Server/DC host or vice versa — the authType-derived apiVersion is wrong; JQL with reserved words unescaped; referencing a project key that was renamed; token expired since credential was saved; corporate proxy terminating TLS with a CA not in caFile.","solutions":["Decode the embedded Jira error JSON in the message — it states the field/permission/JQL problem.","Match credential type to product: Cloud→email+API token (v3), Server/DC→PAT bearer (v2); re-select the credential if mismatched.","For 401/403, rotate and re-enter the token in the credential; for 404, verify jiraHost and apiVersion.","For 400 on JQL, test the query in Jira's issue search first; escape quotes and reserved words.","For TLS errors, attach the correct CA via the caFile input (FILE-STORAGE:: or base64 data URI)."],"exampleFix":"// before — Cloud credential used against Server/DC -> 404 on /rest/api/3/\nauthType='basic', apiVersion='3', host='https://jira.corp.com'\n// after — PAT credential, apiVersion derived to 2\nauthType='bearer', bearerToken='<PAT>'","handlingStrategy":"try-catch","validationCode":"function assertJiraReachable(host: string, authHeader: string, apiVersion: '2'|'3') {\n  return fetch(`${host}/rest/api/${apiVersion}/serverInfo`, { headers: { Authorization: authHeader } })\n    .then(r => { if (!r.ok) throw new Error(`Jira probe ${r.status}`) })\n}","typeGuard":"function isJiraError(e: unknown): e is Error {\n  return e instanceof Error && /^Jira API Error \\d{3}:/.test(e.message)\n}","tryCatchPattern":"try {\n  return await tool.invoke(args)\n} catch (e) {\n  if (isJiraError(e)) {\n    const code = Number(e.message.match(/\\b(\\d{3})\\b/)?.[1])\n    if (code === 401) await rotateJiraToken()\n    if (code === 400 && /jql/i.test(e.message)) throw new Error('bad JQL', { cause: e })\n  }\n  throw e\n}","preventionTips":["Match credential type to product so the derived apiVersion is correct.","Test JQL in Jira's search UI before wiring into list_issues.","Rotate and re-enter tokens on 401; verify project keys on 404.","Supply the correct CA via caFile for self-signed Jira instances."],"tags":["jira","http","api-error","auth","jql"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}