{"record":{"id":"58d488d27d4afd40","repo":"can1357/oh-my-pi","slug":"firecrawl-api-error-response-status-errort","errorCode":null,"errorMessage":"Firecrawl API error (${response.status}): ${errorText}","messagePattern":"Firecrawl API error \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"SearchProviderError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/web/search/providers/firecrawl.ts","lineNumber":133,"sourceCode":"): Promise<FirecrawlSearchResponse> {\n\tconst headers: Record<string, string> = {\n\t\t\"Content-Type\": \"application/json\",\n\t};\n\tif (apiKey) {\n\t\theaders.Authorization = `Bearer ${apiKey}`;\n\t}\n\tconst response = await (params.fetch ?? fetch)(resolveSearchUrl(), {\n\t\tmethod: \"POST\",\n\t\theaders,\n\t\tbody: JSON.stringify(buildRequestBody(params)),\n\t\tsignal: withHardTimeout(params.signal, params.timeoutMs),\n\t});\n\n\tif (!response.ok) {\n\t\tconst errorText = await response.text();\n\t\tconst classified = classifyProviderHttpError(\"firecrawl\", response.status, errorText);\n\t\tif (classified) throw classified;\n\t\tthrow new SearchProviderError(\n\t\t\t\"firecrawl\",\n\t\t\t`Firecrawl API error (${response.status}): ${errorText}`,\n\t\t\tresponse.status,\n\t\t);\n\t}\n\n\tconst data = (await response.json()) as FirecrawlSearchResponse;\n\tif (data.success === false) {\n\t\tthrow new SearchProviderError(\"firecrawl\", data.error?.trim() || \"Firecrawl request failed\");\n\t}\n\treturn data;\n}\n\n/** ISO `YYYY-MM-DD` to Google `MM/DD/YYYY` for `tbs=cdr` custom date ranges. */\nfunction toGoogleDate(iso: string): string {\n\tconst [year, month, day] = iso.split(\"-\");\n\treturn `${month}/${day}/${year}`;\n}","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/web/search/providers/firecrawl.ts#L115-L151","documentation":"callFirecrawlSearch() throws this when the Firecrawl /search endpoint responds with a non-OK HTTP status that the generic classifier (classifyProviderHttpError) did not map to a more specific error. The message embeds the status code and the raw response body text, giving you the provider's own error explanation.","triggerScenarios":"Any non-2xx response from Firecrawl /search: 401/403 from an invalid or expired FIRECRAWL_API_KEY, 402 when out of credits, 429 rate limiting, 5xx server-side errors, or provider-side validation errors with unusual bodies that the classifier does not recognize.","commonSituations":"Expired or wrong API key, exhausted Firecrawl plan credits, hitting rate limits during bulk searches, or Firecrawl incident/outage.","solutions":["Read the embedded status and errorText in the message: it usually states the exact cause (invalid key, quota, bad parameter)","Verify FIRECRAWL_API_KEY is correct and active in the Firecrawl dashboard","Check your plan credits/usage and wait out 429 rate limits with backoff","Check the Firecrawl status page for outages and retry transient 5xx later"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// No pre-call validation possible; verify credentials ahead of time via a cheap authenticated call:\nconst res = await fetch(`${baseUrl}/v2/search`, { method: \"POST\", headers: { Authorization: `Bearer ${key}` }, body: \"{}\" });\nif (res.status === 401 || res.status === 402) throw new Error(\"Firecrawl key invalid or out of credits\");","typeGuard":null,"tryCatchPattern":"import { SearchProviderError } from \"...\";\ntry {\n  results = await firecrawlSearch(query);\n} catch (err) {\n  if (err instanceof SearchProviderError && err.status === 429) {\n    await Bun.sleep(backoffMs); // retry with exponential backoff\n  } else if (err instanceof SearchProviderError && (err.status === 401 || err.status === 403)) {\n    logger.error(\"Firecrawl auth failed — refresh FIRECRAWL_API_KEY\");\n  } else throw err;\n}","preventionTips":["Monitor Firecrawl credit/quota usage before hitting limits","Implement exponential backoff for 429/5xx statuses","Rotate and validate FIRECRAWL_API_KEY regularly; fail fast on 401 at startup","Subscribe to the provider status page to anticipate outages"],"tags":["network","http-error","api-provider"],"backgroundTag":"http-api-error","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}