{"record":{"id":"302cc2694c2a3e9b","repo":"remotion-dev/remotion","slug":"pass-at-least-one-subset-to-loadvariablefont","errorCode":null,"errorMessage":"Pass at least one subset to loadVariableFont()","messagePattern":"Pass at least one subset to loadVariableFont\\(\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/google-fonts/src/base.ts","lineNumber":263,"sourceCode":"\t\twaitUntilDone: () => Promise.all<void>(promises).then(() => undefined),\n\t};\n};\n\nexport const loadVariableFonts = (\n\tmeta: FontInfo,\n\tstyle: string,\n\toptions: FontLoadOptions & {subsets: string[]},\n): {\n\tfontFamily: FontInfo['fontFamily'];\n\taxes: Record<string, {min: number; max: number}>;\n\twaitUntilDone: () => Promise<undefined>;\n} => {\n\tif (!meta.variable) {\n\t\tthrow new Error(`${meta.fontFamily} is not available as a variable font`);\n\t}\n\n\tif (options.subsets.length === 0) {\n\t\tthrow new Error('Pass at least one subset to loadVariableFont()');\n\t}\n\n\tconst fontFacesForStyle = meta.variable.fontFaces.filter(\n\t\t(fontFace) => fontFace.style === style,\n\t);\n\tif (fontFacesForStyle.length === 0) {\n\t\tthrow new Error(\n\t\t\t`The variable font ${meta.fontFamily} does not have a style ${style}`,\n\t\t);\n\t}\n\n\tconst availableSubsetKeys = fontFacesForStyle.map(\n\t\t(fontFace) => fontFace.subset,\n\t);\n\tconst subsets = [\n\t\t...new Set(\n\t\t\toptions.subsets.flatMap((requestedSubset) =>\n\t\t\t\tresolveFontSubsetKeys({","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/google-fonts/src/base.ts#L245-L281","documentation":"loadVariableFont() loads a Google variable font but requires the caller to explicitly list which Unicode subsets (e.g. 'latin', 'cyrillic') to load. The library throws this error when options.subsets is an empty array, because loading zero subsets would produce no usable @font-face resources. It is a fail-fast validation of a required, non-empty option.","triggerScenarios":"Calling loadVariableFont() (via loadVariableFonts) with an options object whose subsets property is [], e.g. loadVariableFont(meta, {subsets: [], style: 'normal'}), typically because subsets were built dynamically from a filter or variable that resolved to nothing.","commonSituations":"Deriving subsets from user config or metadata where the list ends up empty (e.g. filtering subsets that no longer exist in the current @remotion/google-fonts version); copy-pasting the function call and forgetting to fill in subsets; generating the call from code that emits an empty array literal.","solutions":["Pass at least one valid subset name in options.subsets, e.g. {subsets: ['latin']}","Check which subsets the font actually supports via the font's metadata (meta.subsets) and include the ones you need","If subsets are computed dynamically, validate the array is non-empty (or fall back to ['latin']) before calling"],"exampleFix":"// before\nawait loadVariableFont(font, {style: 'normal', subsets: []});\n// after\nawait loadVariableFont(font, {style: 'normal', subsets: ['latin']});","handlingStrategy":"validation","validationCode":"if (!Array.isArray(options.subsets) || options.subsets.length === 0) {\n  throw new Error('loadVariableFont() requires at least one subset, e.g. [\"latin\"]');\n}","typeGuard":"function hasSubsets(o: {subsets?: string[]} | null): o is {subsets: string[]} {\n  return !!o && Array.isArray(o.subsets) && o.subsets.length > 0;\n}","tryCatchPattern":"try {\n  await loadVariableFont(font, {style: 'normal', subsets});\n} catch (e) {\n  if ((e as Error).message.includes('Pass at least one subset')) {\n    await loadVariableFont(font, {style: 'normal', subsets: ['latin']});\n  } else throw e;\n}","preventionTips":["Never pass a literal empty array to subsets","Default dynamic subset lists to ['latin'] when the computed list is empty","Validate subsets against the font's metadata before calling"],"tags":["fonts","validation","api-misuse"],"backgroundTag":"empty-required-field","analyzedSha":"46a3a6bf13ca367376ff18bbb06dae2e87e0d068","analyzedAt":"2026-09-18T00:12:20.256Z","contentChangedAt":"2026-09-18T00:12:20.256Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}