mastra-ai/mastra · error · Error
${response.error || 'Scraping failed'}
Error message
${response.error || 'Scraping failed'} What it means
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.
Source
Thrown at packages/mcp/src/__fixtures__/fire-crawl-complex-schema.ts:639
switch (originalName) {
case 'firecrawl_scrape': {
if (!isScrapeOptions(args)) {
throw new Error('Invalid arguments for firecrawl_scrape');
}
const { url, ...options } = args;
try {
const scrapeStartTime = Date.now();
safeLog('info', `Starting scrape for URL: ${url} with options: ${JSON.stringify(options)}`);
const response = await client.scrapeUrl(url, {
...options,
});
safeLog('info', `Scrape completed in ${Date.now() - scrapeStartTime}ms`);
if ('success' in response && !response.success) {
throw new Error(response.error || 'Scraping failed');
}
const contentParts = [];
if (options.formats?.includes('markdown') && response.markdown) {
contentParts.push(response.markdown);
}
if (options.formats?.includes('html') && response.html) {
contentParts.push(response.html);
}
if (options.formats?.includes('rawHtml') && response.rawHtml) {
contentParts.push(response.rawHtml);
}
if (options.formats?.includes('links') && response.links) {
contentParts.push(response.links.join('\n'));
}
if (options.formats?.includes('screenshot') && response.screenshot) {
contentParts.push(response.screenshot);View on GitHub (pinned to 75dd419e61)
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).
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: key and URL sanity checks
if (!process.env.FIRECRAWL_API_KEY) throw new Error('FIRECRAWL_API_KEY missing');
new URL(input.url); // throws on malformed URL Type guard
function isFailedScrape(r: unknown): r is { success: false; error?: string } {
return typeof r === 'object' && r !== null && 'success' in r && (r as any).success === false;
} Try / catch
try {
const res = await client.scrapeUrl(url, { formats: ['markdown'] });
if ('success' in res && !res.success) throw new Error(res.error || 'Scraping failed');
} catch (e) {
const msg = (e as Error).message;
if (/401|403|unauthorized/i.test(msg)) rotateApiKey();
else if (/credit|quota/i.test(msg)) escalateToBilling();
else if (/timeout|blocked/i.test(msg)) await scrapeWithLongerTimeout(url);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ${response.error}
- State token has expired
- Clerk JWKS URI, secret key and publishable key are required,
- Cookie password must be at least 32 characters for SSO. Set
- Redirect URI is required for SSO login
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/f1e125e97e445660.
Report an issue: GitHub.