shadcn-ui/ui · error

Font "${designSystemConfig.font}" not found

Error message

Font "${designSystemConfig.font}" not found

What it means

buildLayoutFile() resolves the body font via getBodyFont(designSystemConfig.font) and throws if it returns undefined. The font must be one of the registered body fonts (see FONTS in fonts.ts / font-definitions). This function generates the Next.js root layout, so an unknown font blocks payload generation.

Source

Thrown at apps/v4/app/(app)/(create)/lib/v0.ts:391

    null,
    2
  )

  return registryItemFileSchema.parse({
    path: "package.json",
    type: "registry:file",
    target: "package.json",
    content,
  })
}

function buildLayoutFile(
  designSystemConfig: DesignSystemConfig,
  fontHeading: DesignSystemConfig["fontHeading"]
) {
  const font = getBodyFont(designSystemConfig.font)
  if (!font) {
    throw new Error(`Font "${designSystemConfig.font}" not found`)
  }

  const headingFont =
    fontHeading === "inherit" ? undefined : getHeadingFont(fontHeading)

  // Derive const name from the font's CSS variable (e.g. --font-sans → fontSans).
  const constName = font.font.variable
    .replace(/^--/, "")
    .replace(/-./g, (m) => m[1].toUpperCase())
  const headingConstName = "fontHeading"

  // Add font-serif or font-mono class to body when needed. Sans is the default.
  const fontClass =
    font.font.variable === "--font-serif"
      ? "font-serif"
      : font.font.variable === "--font-mono"
        ? "font-mono"
        : ""

View on GitHub (pinned to efac598707)

Solutions

  1. Confirm designSystemConfig.font is a body-eligible font returned by getBodyFont.
  2. Validate the font id against the FONTS list before building the payload.
  3. If the user picked an invalid body font, fall back to a known default like "geist".

Example fix

// before
buildV0Payload({ ...config, font: "playfair-display" }) // not a body font in this setup

// after
const font = getBodyFont(config.font) ? config.font : "geist"
buildV0Payload({ ...config, font })
Defensive patterns

Strategy: validation

Validate before calling

import { getBodyFont } from "@/app/(app)/(create)/lib/fonts"
if (!getBodyFont(config.font)) {
  config = { ...config, font: "geist" } // sane default body font
}

Type guard

import { FONTS } from "@/app/(app)/(create)/lib/fonts"
const BODY_FONT_NAMES = new Set(FONTS.map((f) => f.value))
const isBodyFont = (n: string): n is string => BODY_FONT_NAMES.has(n)

Try / catch

try {
  await buildV0Payload(config)
} catch (e) {
  if (/Font .* not found/.test((e as Error).message)) {
    config = { ...config, font: "geist" }
  } else throw e
}

Prevention

When it happens

Trigger: Passing font: "inherit" or an unregistered font id to buildV0Payload; using a heading-only font as the body font; a font id renamed in the registry.

Common situations: Presetting a font from URL or client state without validating against FONTS; confusing heading font ids with body font ids.

Related errors


AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12). Data as JSON: /api/errors/b2d11a4ec1f3ed8e. Report an issue: GitHub.