{"record":{"id":"108c82fb8e6431c7","repo":"eyaltoledano/claude-task-master","slug":"this-name-api-error-during-operation-erro","errorCode":null,"errorMessage":"${this.name} API error during ${operation}: ${errorMessage}","messagePattern":"(.+?) API error during (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/ai-providers/base-provider.js","lineNumber":257,"sourceCode":"\n\t\tfor (const msg of messages) {\n\t\t\tif (!msg.role || !msg.content) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Invalid message format. Each message must have role and content'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Common error handler\n\t */\n\thandleError(operation, error) {\n\t\tconst errorMessage = error.message || 'Unknown error occurred';\n\t\tlog('error', `${this.name} ${operation} failed: ${errorMessage}`, {\n\t\t\terror\n\t\t});\n\t\tthrow new Error(\n\t\t\t`${this.name} API error during ${operation}: ${errorMessage}`\n\t\t);\n\t}\n\n\t/**\n\t * Creates and returns a client instance for the provider\n\t * @abstract\n\t */\n\tgetClient(params) {\n\t\tthrow new Error('getClient must be implemented by provider');\n\t}\n\n\t/**\n\t * Returns if the API key is required\n\t * @abstract\n\t * @returns {boolean} if the API key is required, defaults to true\n\t */\n\tisRequiredApiKey() {","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/src/ai-providers/base-provider.js#L239-L275","documentation":"BaseAIProvider.handleError wraps any error thrown during a provider operation into a normalized Error with the pattern '<ProviderName> API error during <operation>: <original message>'. It is the single catch-path used by generateText, streamText, generateObject and streamObject, so almost any downstream failure (auth, network, bad model, SDK error) surfaces in this form.","triggerScenarios":"Any exception thrown inside the try block of generateText/streamText/generateObject/streamObject: SDK client errors, network failures, invalid model IDs, API 4xx/5xx responses, or errors rethrown from validateParams/validateMessages within those methods.","commonSituations":"Expired or wrong API keys, rate limits (429), nonexistent model IDs after a provider renamed models, network timeouts, DNS failures, or a provider SDK throwing on malformed requests.","solutions":["Read the trailing original message after 'API error during <operation>:' — that is the root cause","Log/check the underlying error: handleError already log('error', ...) with the error object","For auth messages, verify the provider's API key env var; for model errors, verify modelId against provider docs","Add retry with backoff for transient network/rate-limit messages"],"exampleFix":"// before\ncatch (e) { /* vague handling of wrapped error */ }\n// after\ncatch (e) {\n  if (e.message.includes('API error during generateText: 401')) {\n    // fix credentials\n  } else if (/429|rate/i.test(e.message)) {\n    // retry with backoff\n  }\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  await provider.generateText({ messages, modelId });\n} catch (e) {\n  const wrapped = e.message.startsWith(provider.name + ' API error during ');\n  if (wrapped) {\n    const rootCause = e.message.split(': ').slice(1).join(': ');\n    console.error('Provider op failed:', rootCause);\n    // decide retry vs abort based on rootCause (429/timeout -> retry; 401 -> fix creds)\n  } else throw e;\n}","preventionTips":["Parse the text after 'API error during <operation>:' to get the root cause","Distinguish transient (rate limit, timeout) from permanent (auth, model) causes before retrying","Log the full error object — handleError already logs it via log('error', ...)"],"tags":["api-error","error-wrapping","provider"],"backgroundTag":"api-error-wrapped","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}