DavidHDev/react-bits · warning · Error

Failed to fetch font stylesheet (${response.status})

Error message

Failed to fetch font stylesheet (${response.status})

What it means

loadFontFromStylesheet fetches a CSS file (Google Fonts Figtree by default) and throws when response.ok is false. The HTTP status is embedded in the message. This is a network/HTTP-level failure on the font CSS request; the font files themselves are fetched later. The outer resolveFont (line 116-119) catches this and falls back to the default font string, so it is non-fatal to rendering.

Source

Thrown at src/ts-tailwind/Components/CircularGallery/CircularGallery.tsx:40

      instance[key] = instance[key].bind(instance);
    }
  });
}

const DEFAULT_FONT = 'bold 30px Figtree';
// Figtree is not guaranteed to be available on the host page, so the component
// loads it on demand whenever the default font is used.
const DEFAULT_FONT_URL = 'https://fonts.googleapis.com/css2?family=Figtree:wght@400;700&display=swap';

function deriveFontFamilyFromUrl(url: string): string {
  const fileName = (url.split('/').pop() || 'custom-font').split('?')[0];
  const base = fileName.replace(/\.(woff2?|ttf|otf|eot)$/i, '');
  return base.replace(/[^a-zA-Z0-9-_ ]/g, '').trim() || 'CircularGalleryFont';
}

async function loadFontFromStylesheet(url: string): Promise<string> {
  const response = await fetch(url);
  if (!response.ok) throw new Error(`Failed to fetch font stylesheet (${response.status})`);
  const cssText = await response.text();
  const faceBlocks = cssText.match(/@font-face\s*{[^}]*}/g) || [];
  let family: string | null = null;
  const fontFaces: FontFace[] = [];
  for (const block of faceBlocks) {
    const familyMatch = block.match(/font-family:\s*['"]?([^;'"]+)['"]?/);
    const urlMatch = block.match(/url\(\s*['"]?([^'")]+)['"]?\s*\)/);
    if (!familyMatch || !urlMatch) continue;
    family = familyMatch[1].trim();
    const descriptors: FontFaceDescriptors = {};
    const weightMatch = block.match(/font-weight:\s*([^;]+);/);
    const styleMatch = block.match(/font-style:\s*([^;]+);/);
    const rangeMatch = block.match(/unicode-range:\s*([^;]+);/);
    if (weightMatch) descriptors.weight = weightMatch[1].trim();
    if (styleMatch) descriptors.style = styleMatch[1].trim();
    if (rangeMatch) descriptors.unicodeRange = rangeMatch[1].trim();
    fontFaces.push(new FontFace(family, `url(${urlMatch[1]})`, descriptors));
  }

View on GitHub (pinned to c7109dccb4)

Solutions

  1. Allow the font host in CSP: add fonts.googleapis.com and fonts.gstatic.com to connect-src and font-src.
  2. Verify network reachability to the stylesheet URL from the user's environment (e.g. curl -I the URL).
  3. Bundle the font file locally and pass a direct .woff2 URL via the fontUrl prop instead of the Google stylesheet.
  4. Rely on the built-in fallback: resolveFont already catches this and renders with the default font — confirm the error is only logged, not crashing.

Example fix

// before
const DEFAULT_FONT_URL = 'https://fonts.googleapis.com/css2?family=Figtree:wght@400;700&display=swap';

// after (self-host to remove network/CSP dependency)
import figtreeUrl from './assets/Figtree.woff2';
<CircularGallery fontUrl={figtreeUrl} />

// and relax CSP only if still using Google Fonts:
// Content-Security-Policy: ... connect-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com;
Defensive patterns

Strategy: try-catch

Validate before calling

async function canFetchStylesheet(url: string): Promise<boolean> {
  try {
    const r = await fetch(url, { method: 'GET' });
    return r.ok;
  } catch { return false; }
}

Try / catch

// resolveFont already does this (CircularGallery.tsx:116-119):
try {
  const family = await loadCustomFont(effectiveUrl);
  return `${prefix} "${family}"`;
} catch (error) {
  console.error('CircularGallery: unable to load font from', fontUrl, error);
  return font; // fall back to the default font string
}

Prevention

When it happens

Trigger: fetch(url).then(r => !r.ok -> throw) at src/ts-tailwind/Components/CircularGallery/CircularGallery.tsx:40, where url is DEFAULT_FONT_URL ('https://fonts.googleapis.com/css2?family=Figtree...') or a caller-supplied fontUrl matched as a stylesheet (line 78).

Common situations: Offline or blocked network; Content-Security-Policy connect-src/font-src blocking fonts.googleapis.com; corporate firewall/proxy returning a 4xx/5xx intercept page; Google Fonts rate-limiting (429); geographic blocking; jsdom where fetch is a stub returning non-ok; invalid/expired stylesheet URL.

Related errors


AI-assisted analysis of DavidHDev/react-bits@c7109dccb4 (2026-08-13). Data as JSON: /api/errors/96fa548af007273e. Report an issue: GitHub.