{"record":{"id":"957d5feccbbe851c","repo":"mastra-ai/mastra","slug":"extractresponse-error-extraction-failed","errorCode":null,"errorMessage":"${extractResponse.error || 'Extraction failed'}","messagePattern":"\\$\\{extractResponse\\.error \\|\\| 'Extraction failed'\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/__fixtures__/fire-crawl-complex-schema.ts","lineNumber":809,"sourceCode":"          const extractStartTime = Date.now();\n\n          safeLog('info', `Starting extraction for URLs: ${args.urls.join(', ')}`);\n\n          const extractResponse = await withRetry(\n            async () =>\n              client.extract(args.urls, {\n                prompt: args.prompt,\n                systemPrompt: args.systemPrompt,\n                schema: args.schema,\n                allowExternalLinks: args.allowExternalLinks,\n                enableWebSearch: args.enableWebSearch,\n                includeSubdomains: args.includeSubdomains,\n              } as ExtractParams),\n            'extract operation',\n          );\n\n          if (!('success' in extractResponse) || !extractResponse.success) {\n            throw new Error(extractResponse.error || 'Extraction failed');\n          }\n\n          const response = extractResponse as ExtractResponse;\n\n          safeLog('info', `Extraction completed in ${Date.now() - extractStartTime}ms`);\n\n          const result = {\n            content: [\n              {\n                type: 'text',\n                text: trimResponseText(JSON.stringify(response.data, null, 2)),\n              },\n            ],\n            isError: false,\n          };\n\n          if (response.warning) {\n            safeLog('warning', response.warning);","sourceCodeStart":791,"sourceCodeEnd":827,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp/src/__fixtures__/fire-crawl-complex-schema.ts#L791-L827","documentation":"The extract operation's response from client.extract() (via withRetry) is checked for `success` in response and response.success. When the Firecrawl extract API reports failure, the server throws the API-provided error message or the fallback 'Extraction failed'. Extract is an asynchronous job endpoint, so failures also occur when the job is not found, times out, or is cancelled.","triggerScenarios":"extractResponse.success is falsy or the response lacks a success field — invalid API key, rate limits, invalid URLs rejected server-side, extract job failed/expired/not found, or a timeout while withRetry still returned a non-success envelope.","commonSituations":"Extracting from sites that block scraping or require JS login; job submitted but poll expired before completion; credits exhausted for the batch of URLs; older SDK versions returning responses without the success field.","solutions":["Read extractResponse.error for the underlying cause (auth, credits, invalid URL, job state).","Verify API key validity and remaining extract credits in the Firecrawl dashboard.","Retry with ignoreInvalidURLs: true so bad URLs don't fail the whole extract job.","Increase poll/timeout parameters and re-check job status if the job timed out before completion."],"exampleFix":"// before\nif (!('success' in extractResponse) || !extractResponse.success) {\n  throw new Error(extractResponse.error || 'Extraction failed');\n}\n// after\nif (!('success' in extractResponse) || !extractResponse.success) {\n  logger.error('extract failed', extractResponse.error);\n  const retryable = /429|timeout|temporarily/i.test(extractResponse.error ?? '');\n  if (retryable) return retryExtractLater(args);\n  throw new Error(`Extraction failed: ${extractResponse.error ?? 'no detail from API'}`);\n}","handlingStrategy":"retry","validationCode":"// Pre-flight prerequisites for extract jobs:\nif (!process.env.FIRECRAWL_API_KEY) throw new Error('FIRECRAWL_API_KEY missing');\nconst urlRe = /^https?:\\/\\//;\nif (!args.urls.every(u => urlRe.test(u))) throw new TypeError('all urls must be absolute http(s) URLs');","typeGuard":"function isExtractSuccess(res: unknown): res is { success: true; data: unknown } {\n  return typeof res === 'object' && res !== null &&\n    'success' in res && (res as any).success === true;\n}","tryCatchPattern":"try {\n  const res = await firecrawlExtract(args);\n  if (!res.success) throw new Error(res.error || 'Extraction failed');\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  if (/429|timeout|temporarily|job/i.test(msg)) return withBackoff(() => firecrawlExtract(args), 3);\n  if (/401|403|credit/i.test(msg)) throw new Error('Firecrawl auth/credits problem: ' + msg);\n  throw e;\n}","preventionTips":["Retry extract jobs with exponential backoff; jobs can fail transiently.","Track extract credit usage — batch jobs consume credits per URL.","Use ignoreInvalidURLs: true so one blocked URL doesn't fail the whole job.","Keep the SDK updated; older versions may omit the success field."],"tags":["network","api-error","firecrawl","async-job"],"backgroundTag":"api-request-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}