{"record":{"id":"b2d11a4ec1f3ed8e","repo":"shadcn-ui/ui","slug":"font-designsystemconfig-font-not-found","errorCode":null,"errorMessage":"Font \"${designSystemConfig.font}\" not found","messagePattern":"Font \"(.+?)\" not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/v4/app/(app)/(create)/lib/v0.ts","lineNumber":391,"sourceCode":"    null,\n    2\n  )\n\n  return registryItemFileSchema.parse({\n    path: \"package.json\",\n    type: \"registry:file\",\n    target: \"package.json\",\n    content,\n  })\n}\n\nfunction buildLayoutFile(\n  designSystemConfig: DesignSystemConfig,\n  fontHeading: DesignSystemConfig[\"fontHeading\"]\n) {\n  const font = getBodyFont(designSystemConfig.font)\n  if (!font) {\n    throw new Error(`Font \"${designSystemConfig.font}\" not found`)\n  }\n\n  const headingFont =\n    fontHeading === \"inherit\" ? undefined : getHeadingFont(fontHeading)\n\n  // Derive const name from the font's CSS variable (e.g. --font-sans → fontSans).\n  const constName = font.font.variable\n    .replace(/^--/, \"\")\n    .replace(/-./g, (m) => m[1].toUpperCase())\n  const headingConstName = \"fontHeading\"\n\n  // Add font-serif or font-mono class to body when needed. Sans is the default.\n  const fontClass =\n    font.font.variable === \"--font-serif\"\n      ? \"font-serif\"\n      : font.font.variable === \"--font-mono\"\n        ? \"font-mono\"\n        : \"\"","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/apps/v4/app/(app)/(create)/lib/v0.ts#L373-L409","documentation":"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.","triggerScenarios":"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.","commonSituations":"Presetting a font from URL or client state without validating against FONTS; confusing heading font ids with body font ids.","solutions":["Confirm designSystemConfig.font is a body-eligible font returned by getBodyFont.","Validate the font id against the FONTS list before building the payload.","If the user picked an invalid body font, fall back to a known default like \"geist\"."],"exampleFix":"// before\nbuildV0Payload({ ...config, font: \"playfair-display\" }) // not a body font in this setup\n\n// after\nconst font = getBodyFont(config.font) ? config.font : \"geist\"\nbuildV0Payload({ ...config, font })","handlingStrategy":"validation","validationCode":"import { getBodyFont } from \"@/app/(app)/(create)/lib/fonts\"\nif (!getBodyFont(config.font)) {\n  config = { ...config, font: \"geist\" } // sane default body font\n}","typeGuard":"import { FONTS } from \"@/app/(app)/(create)/lib/fonts\"\nconst BODY_FONT_NAMES = new Set(FONTS.map((f) => f.value))\nconst isBodyFont = (n: string): n is string => BODY_FONT_NAMES.has(n)","tryCatchPattern":"try {\n  await buildV0Payload(config)\n} catch (e) {\n  if (/Font .* not found/.test((e as Error).message)) {\n    config = { ...config, font: \"geist\" }\n  } else throw e\n}","preventionTips":["Drive font selectors from FONTS, not free-text input.","Default the body font to a known-good id like \"geist\"."],"tags":["fonts","v0","layout","validation"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}