{"record":{"id":"dc377c77ffe56998","repo":"eyaltoledano/claude-task-master","slug":"api-request-failed-response-status-errorte","errorCode":null,"errorMessage":"API request failed: ${response.status} - ${errorText}","messagePattern":"API request failed: (.+?) - (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/integration/services/export.service.ts","lineNumber":703,"sourceCode":"\t\t\t// Get auth token\n\t\t\tconst accessToken = await this.authManager.getAccessToken();\n\t\t\tif (!accessToken) {\n\t\t\t\tthrow new Error('Not authenticated');\n\t\t\t}\n\n\t\t\t// Make API request\n\t\t\tconst response = await fetch(apiUrl, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\tAuthorization: `Bearer ${accessToken}`\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(requestBody)\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorText = await response.text();\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`API request failed: ${response.status} - ${errorText}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst result = (await response.json()) as BulkTasksResponse;\n\n\t\t\tif (result.failedCount > 0) {\n\t\t\t\tconst failedTasks = result.results\n\t\t\t\t\t.filter((r) => !r.success)\n\t\t\t\t\t.map((r) => `${r.externalId}: ${r.error}`)\n\t\t\t\t\t.join(', ');\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Warning: ${result.failedCount} tasks failed to import: ${failedTasks}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`Successfully exported ${result.successCount} of ${result.totalTasks} tasks to brief ${briefId}`","sourceCodeStart":685,"sourceCodeEnd":721,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/integration/services/export.service.ts#L685-L721","documentation":"performExport() POSTs the task payload to the export API endpoint and checks response.ok. On any non-2xx response it reads the body and throws a plain Error of the form 'API request failed: <status> - <body>'. This surfaces server-side rejections (4xx/5xx) from the bulk-task export endpoint, including the raw response text for diagnosis.","triggerScenarios":"The export HTTP call returns a non-OK status: 400 malformed payload, 401/403 expired or insufficient-permission token, 404 wrong API base URL/path, 409 conflict, 413 payload too large (very large task sets), 429 rate limit, or 5xx server error.","commonSituations":"Expired token mid-session (401); exporting thousands of tasks exceeding body-size limits (413); brief or org deleted server-side between validation and export (404); API outage or deploy in progress (502/503); misconfigured TM_PUBLIC_BASE_DOMAIN pointing at the wrong environment.","solutions":["Read the status and body in the error message — it contains the server's diagnostic text.","For 401/403, re-authenticate (`tm auth login`) and confirm org/brief permissions.","For 413/429, export in smaller batches or retry after backoff.","For 5xx, retry with exponential backoff; if persistent, check the service status / API base domain configuration.","For 404, verify TM_PUBLIC_BASE_DOMAIN points to the correct API environment."],"exampleFix":"// before\nawait exportService.exportTasks(options); // throws on any 4xx/5xx\n// after — wrap with retry for transient failures\ntry {\n  await exportService.exportTasks(options);\n} catch (e) {\n  if (/API request failed: (5\\d\\d|429)/.test(e.message)) {\n    await retryWithBackoff(() => exportService.exportTasks(options));\n  } else throw e;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"async function exportWithRetry(options, maxRetries = 3) {\n  for (let attempt = 1; attempt <= maxRetries; attempt++) {\n    try {\n      return await exportService.exportTasks(options);\n    } catch (e) {\n      const m = /API request failed: (\\d{3})/.exec(e.message);\n      const status = m ? Number(m[1]) : 0;\n      if (status === 429 || status >= 500) {\n        await new Promise(r => setTimeout(r, 2 ** attempt * 500));\n        continue;\n      }\n      if (status === 401 || status === 403) {\n        await tmCore.auth.login(); // refresh credentials, then retry once\n        continue;\n      }\n      throw e;\n    }\n  }\n  throw new Error('Export failed after retries');\n}","preventionTips":["Re-authenticate before long-running exports so tokens don't expire mid-call","Chunk very large task sets to avoid 413 payload-size rejections","Verify TM_PUBLIC_BASE_DOMAIN points at the intended API environment","Build exponential backoff around the export call for 429/5xx resilience","Monitor the response body in error messages — it carries the server's diagnostic detail"],"tags":["network","http","export","api"],"backgroundTag":"http-request-failed","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}