{"record":{"id":"f1e125e97e445660","repo":"mastra-ai/mastra","slug":"response-error-scraping-failed","errorCode":null,"errorMessage":"${response.error || 'Scraping failed'}","messagePattern":"\\$\\{response\\.error \\|\\| 'Scraping failed'\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/__fixtures__/fire-crawl-complex-schema.ts","lineNumber":639,"sourceCode":"\n    switch (originalName) {\n      case 'firecrawl_scrape': {\n        if (!isScrapeOptions(args)) {\n          throw new Error('Invalid arguments for firecrawl_scrape');\n        }\n        const { url, ...options } = args;\n        try {\n          const scrapeStartTime = Date.now();\n          safeLog('info', `Starting scrape for URL: ${url} with options: ${JSON.stringify(options)}`);\n\n          const response = await client.scrapeUrl(url, {\n            ...options,\n          });\n\n          safeLog('info', `Scrape completed in ${Date.now() - scrapeStartTime}ms`);\n\n          if ('success' in response && !response.success) {\n            throw new Error(response.error || 'Scraping failed');\n          }\n\n          const contentParts = [];\n\n          if (options.formats?.includes('markdown') && response.markdown) {\n            contentParts.push(response.markdown);\n          }\n          if (options.formats?.includes('html') && response.html) {\n            contentParts.push(response.html);\n          }\n          if (options.formats?.includes('rawHtml') && response.rawHtml) {\n            contentParts.push(response.rawHtml);\n          }\n          if (options.formats?.includes('links') && response.links) {\n            contentParts.push(response.links.join('\\n'));\n          }\n          if (options.formats?.includes('screenshot') && response.screenshot) {\n            contentParts.push(response.screenshot);","sourceCodeStart":621,"sourceCodeEnd":657,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp/src/__fixtures__/fire-crawl-complex-schema.ts#L621-L657","documentation":"After `client.scrapeUrl` returns, the executor checks `response.success`; when it is explicitly false it throws `response.error || 'Scraping failed'`. This surfaces a Firecrawl API-side failure (bad key, blocked page, scrape timeout) as the tool's error message. Note the inner try/catch converts it into an `isError: true` MCP result rather than a thrown exception.","triggerScenarios":"Any scrape where the Firecrawl API responds with success:false — invalid/expired API key, credits exhausted, target URL unreachable or blocking crawlers (403/timeout), or an unsupported format combination.","commonSituations":"FIRECRAWL_API_KEY not set or rotated, free-tier credit limits hit, scraping sites protected by Cloudflare/bot walls, scraping URLs that require JS rendering without `waitUntil`/timeout tuning.","solutions":["Read the `response.error` message; fix the underlying cause it names (auth, credits, URL).","Verify FIRECRAWL_API_KEY is valid and has remaining credits in the Firecrawl dashboard.","Retry with adjusted scrape options (longer timeout, waitUntil, formats limited to markdown).","Add rate-limit/backoff handling (the fixture's withRetry only covers the crawl path)."],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"// pre-flight: key and URL sanity checks\nif (!process.env.FIRECRAWL_API_KEY) throw new Error('FIRECRAWL_API_KEY missing');\nnew URL(input.url); // throws on malformed URL","typeGuard":"function isFailedScrape(r: unknown): r is { success: false; error?: string } {\n  return typeof r === 'object' && r !== null && 'success' in r && (r as any).success === false;\n}","tryCatchPattern":"try {\n  const res = await client.scrapeUrl(url, { formats: ['markdown'] });\n  if ('success' in res && !res.success) throw new Error(res.error || 'Scraping failed');\n} catch (e) {\n  const msg = (e as Error).message;\n  if (/401|403|unauthorized/i.test(msg)) rotateApiKey();\n  else if (/credit|quota/i.test(msg)) escalateToBilling();\n  else if (/timeout|blocked/i.test(msg)) await scrapeWithLongerTimeout(url);\n}","preventionTips":["Monitor Firecrawl credit usage and set alerts before exhaustion.","Test API key validity at startup with a cheap probe request.","Prefer markdown format and sane timeouts for bot-protected sites.","Log response.warning fields surfaced by successful scrapes."],"tags":["api-response","scraping","auth"],"backgroundTag":"api-request-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}