mastra-ai/mastra · error · Error

${response.error || 'Deep research failed'}

Error message

${response.error || 'Deep research failed'}

What it means

After the deep research job finishes, the executor checks response.success and throws the API's error message, defaulting to 'Deep research failed'. Deep research runs scraping + analysis steps server-side at Firecrawl, so failures include per-page scrape failures aggregated into the job as well as auth/credit/limit issues.

Source

Thrown at packages/mcp/src/__fixtures__/fire-crawl-complex-schema.ts:868

          const response = await client.deepResearch(
            args.query as string,
            {
              maxDepth: args.maxDepth as number,
              timeLimit: args.timeLimit as number,
              maxUrls: args.maxUrls as number,
            },
            activity => {
              safeLog('info', `Research activity: ${activity.message} (Depth: ${activity.depth})`);
            },
            source => {
              safeLog('info', `Research source found: ${source.url}${source.title ? ` - ${source.title}` : ''}`);
            },
          );

          safeLog('info', `Deep research completed in ${Date.now() - researchStartTime}ms`);

          if (!response.success) {
            throw new Error(response.error || 'Deep research failed');
          }

          const formattedResponse = {
            finalAnalysis: response.data.finalAnalysis,
            activities: response.data.activities,
            sources: response.data.sources,
          };

          return {
            content: [
              {
                type: 'text',
                text: trimResponseText(formattedResponse.finalAnalysis),
              },
            ],
            isError: false,
          };
        } catch (error) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Surface response.error to identify whether it was auth, credits, rate limit, or scrape failures.
  2. Reduce job scope (lower maxUrls/maxDepth/timeLimit) to lower cost and failure probability.
  3. Confirm API key and credit balance; upgrade plan if deep research is credit-hungry.
  4. Retry with backoff for transient 429/5xx causes, and check Firecrawl status for outages.

Example fix

// before
if (!response.success) {
  throw new Error(response.error || 'Deep research failed');
}
// after
if (!response.success) {
  const detail = response.error || 'no error detail returned';
  if (/credit|quota/i.test(detail)) throw new Error('Firecrawl credits exhausted: ' + detail);
  if (/rate limit/i.test(detail)) throw new RetryableError(detail);
  throw new Error(`Deep research failed: ${detail}`);
}
Defensive patterns

Strategy: retry

Validate before calling

// Budget pre-check to reduce mid-job failures:
if (!args?.query) throw new TypeError('query required');
if ((args.maxUrls ?? Infinity) * (args.maxDepth ?? Infinity) > 500) {
  console.warn('Deep research job may be credit-expensive; consider lowering maxUrls/maxDepth');
}

Type guard

function isDeepResearchSuccess(res: unknown): res is { success: true; data: { finalAnalysis: string; activities?: unknown[]; sources?: unknown[] } } {
  return typeof res === 'object' && res !== null && (res as any).success === true && !!res.data?.finalAnalysis;
}

Try / catch

try {
  const res = await firecrawlDeepResearch(args);
  if (!res.success) throw new Error(res.error || 'Deep research failed');
} catch (e) {
  const msg = e instanceof Error ? e.message : String(e);
  if (/rate limit|429|temporarily/i.test(msg)) return withBackoff(() => firecrawlDeepResearch(smallerScope(args)), 3);
  if (/credit|quota/i.test(msg)) throw new Error('Insufficient Firecrawl credits for deep research');
  throw e;
}

Prevention

When it happens

Trigger: response.success is false when the research job completes or fails — invalid API key, credit exhaustion mid-job, rate limiting during the many underlying scrape/search calls, or all target pages failing to scrape.

Common situations: Long research jobs hitting credit limits before completion; Firecrawl service degradation during an expensive multi-step job; transient 429s not retried by the outer withRetry because the job already returned success:false.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/a48f39bc300f3ac2. Report an issue: GitHub.