firecrawl/open-lovable · error

Failed to extract brand styles

Error message

Failed to extract brand styles

What it means

Thrown when the brand-styles extraction endpoint returns a non-2xx HTTP status during brand-extension mode. The client posted { url, prompt: brandExtensionPrompt } and extractResponse.ok was false, so the brand guidelines could not be fetched and generation of the brand-matched component cannot proceed. It is a coarse message: the HTTP status/body must be checked separately for the real cause.

Source

Thrown at app/generation/page.tsx:2728

        let scrapeData: ScrapeData | undefined;
        let brandGuidelines: any;

        if (brandExtensionMode) {
          // === BRAND EXTENSION MODE ===
          addChatMessage('Extracting brand styles from the website...', 'system');

          // Call the brand extraction endpoint
          const extractResponse = await fetch('/api/extract-brand-styles', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              url,
              prompt: brandExtensionPrompt
            })
          });

          if (!extractResponse.ok) {
            throw new Error('Failed to extract brand styles');
          }

          brandGuidelines = await extractResponse.json();

          if (!brandGuidelines.success) {
            throw new Error(brandGuidelines.error || 'Failed to extract brand styles');
          }

          // Display branding summary with visual UI
          addChatMessage(`Acquired branding format from ${cleanUrl}`, 'system', {
            brandingData: brandGuidelines.guidelines,
            sourceUrl: cleanUrl
          });
          addChatMessage(`Building your custom component using these brand guidelines...`, 'system');

          // Clear the flags after use
          sessionStorage.removeItem('brandExtensionMode');
          sessionStorage.removeItem('brandExtensionPrompt');

View on GitHub (pinned to 69bd93bae7)

Solutions

  1. Inspect the Network tab for the extraction request's status code and body to see the underlying reason
  2. Validate the URL is well-formed and publicly reachable (try curl-ing it) before retrying
  3. If the site blocks bots (403/Cloudflare), try a different public page of the same brand or a cached version
  4. Check the extraction route's server logs for timeouts or upstream fetch errors and increase its timeout if needed
  5. Retry once for transient 5xx/timeout failures

Example fix

// before
if (!extractResponse.ok) {
  throw new Error('Failed to extract brand styles');
}
// after
if (!extractResponse.ok) {
  let detail = '';
  try { detail = await extractResponse.text(); } catch {}
  throw new Error(`Failed to extract brand styles (${extractResponse.status}): ${detail || extractResponse.statusText}`);
}
Defensive patterns

Strategy: validation

Validate before calling

function isExtractableUrl(url: string): boolean {
  try { const u = new URL(url); return u.protocol === 'http:' || u.protocol === 'https:'; }
  catch { return false; }
}
if (!isExtractableUrl(url)) throw new Error('Enter a valid public http(s) URL');

Type guard

interface BrandGuidelines { success: boolean; error?: string; guidelines?: unknown }
function hasGuidelines(d: unknown): d is BrandGuidelines & { success: true; guidelines: Record<string, unknown> } {
  return typeof d === 'object' && d !== null && (d as BrandGuidelines).success === true && (d as BrandGuidelines).guidelines != null;
}

Try / catch

try {
  const res = await fetch(EXTRACT_URL, { method: 'POST', body: JSON.stringify({ url, prompt: brandExtensionPrompt }) });
  if (!res.ok) throw new Error(`Brand extraction HTTP ${res.status}`);
  brandGuidelines = await res.json();
  if (!hasGuidelines(brandGuidelines)) throw new Error(brandGuidelines?.error || 'No usable brand guidelines extracted');
} catch (err: any) {
  addChatMessage(`Brand extraction failed: ${err.message}. Try another public page.`, 'system');
}

Prevention

When it happens

Trigger: fetch to the extract-brand-styles route resolves with extractResponse.ok === false: the target site blocked scraping (403 from upstream, surfaced as route failure), the route handler threw (invalid URL, fetch timeout), or the route is missing (404).

Common situations: User submits a URL behind a login/Cloudflare protection so server-side scraping is blocked; malformed URL (missing protocol) fails server-side URL validation; extraction route times out on slow sites; deployment lacks the extraction route; target site returns non-HTML content the extractor cannot parse and the route 500s.

Related errors


AI-assisted analysis of firecrawl/open-lovable@69bd93bae7 (2026-08-28). Data as JSON: /api/errors/9fec75d1348cad47. Report an issue: GitHub.