{"record":{"id":"3f2acdfa71991a74","repo":"chenglou/pretext","slug":"no-font-matrix-configured-for-options-id-avail","errorCode":null,"errorMessage":"No font matrix configured for ${options.id}. Available corpora: ${Object.keys(FONT_MATRIX).join(', ')}","messagePattern":"No font matrix configured for (.+?)\\. Available corpora: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/corpus-font-matrix.ts","lineNumber":443,"sourceCode":"  console.log(`${summary.corpusId} — ${summary.title}`)\n  console.log(`widths: ${summary.widths.join(', ')}`)\n  for (const variant of summary.variants) {\n    console.log(`  ${variant.label}: ${variant.exactCount}/${variant.widthCount} exact | ${variant.mismatches.length} nonzero`)\n    console.log(`    ${bucketMismatches(variant.mismatches)}`)\n  }\n}\n\nconst options = parseOptions()\noptions.port = await getAvailablePort(options.port === 0 ? null : options.port)\nconst sources = await loadSources()\nconst meta = sources.find(source => source.id === options.id)\nif (meta === undefined) {\n  throw new Error(`Unknown corpus ${options.id}. Available corpora: ${sources.map(source => source.id).join(', ')}`)\n}\n\nconst variants = FONT_MATRIX[options.id]\nif (variants === undefined) {\n  throw new Error(`No font matrix configured for ${options.id}. Available corpora: ${Object.keys(FONT_MATRIX).join(', ')}`)\n}\n\nconst widths = getSweepWidths(meta, options)\nconst lock = await acquireBrowserAutomationLock(options.browser)\nconst session = createBrowserSession(options.browser)\nlet serverProcess: ChildProcess | null = null\n\ntry {\n  const pageServer = await ensurePageServer(options.port, '/corpus', process.cwd())\n  serverProcess = pageServer.process\n  const baseUrl = `${pageServer.baseUrl}/corpus`\n  const variantResults: VariantResult[] = []\n\n  for (const variant of variants) {\n    const requestId = `${Date.now()}-${variant.id}-${Math.random().toString(36).slice(2)}`\n    const reportServer = await startPostedReportServer<CorpusSweepReport>(requestId)\n    const url =\n      `${baseUrl}?id=${encodeURIComponent(meta.id)}` +","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/chenglou/pretext/blob/ac49b09b7d83ede19581fa94a8b892b07d309baf/scripts/corpus-font-matrix.ts#L425-L461","documentation":"Thrown at the top level of corpus-font-matrix.ts immediately after [37]'s sources.json lookup succeeded. The id IS a real corpus, but it has no entry in the FONT_MATRIX constant (no font variants configured for sweeping). Distinct from [37] (not in sources at all) and from [35] (no id at all). The availability list is the FONT_MATRIX keys, which can be a strict subset of sources.json.","triggerScenarios":"sources.find succeeded (meta is defined) but FONT_MATRIX[options.id] is undefined. Triggers when a corpus exists in sources.json but was never given font variants in the FONT_MATRIX table at the top of corpus-font-matrix.ts. This is a deliberate two-tier config: a corpus must be in both sources.json AND FONT_MATRIX to be sweepable.","commonSituations":"A new corpus was added to sources.json (so it passes [37]) but the contributor forgot to add a FONT_MATRIX entry; using a corpus id copied from corpus-check's availability list (which is sources.json-based) without checking it has font variants; renaming a corpus in sources.json but not in FONT_MATRIX.","solutions":["Pick an id from the FONT_MATRIX keys listed in the error — those are the corpora actually configured for font sweeps.","If you intended to sweep this corpus, add an entry to the FONT_MATRIX constant with at least one FontVariant ({ id, label, font, lineHeight }).","Keep sources.json and FONT_MATRIX in sync when adding/renaming corpora."],"exampleFix":"// before (corpus exists in sources.json but has no font variants)\nbun run scripts/corpus-font-matrix.ts --id=some-corpus-without-variants\n// after — either pick a configured corpus, or add an entry to FONT_MATRIX\n// In corpus-font-matrix.ts:\n//   const FONT_MATRIX = {\n//     ...,\n//     'some-corpus-without-variants': [\n//       { id: 'default', label: 'Serif', font: '20px serif', lineHeight: 32 },\n//     ],\n//   }","handlingStrategy":"validation","validationCode":"const MATRIX_KEYS = new Set(Object.keys(FONT_MATRIX))\nfunction assertHasFontMatrix(id: string): void {\n  if (!MATRIX_KEYS.has(id)) {\n    throw new Error(`No font matrix configured for ${id}. Configured: ${[...MATRIX_KEYS].join(', ')}`)\n  }\n}","typeGuard":"function hasFontMatrix(id: string): boolean {\n  return Object.prototype.hasOwnProperty.call(FONT_MATRIX, id)\n}","tryCatchPattern":null,"preventionTips":["Pick --id from FONT_MATRIX keys (the error lists them), since sources.json is broader.","When adding a corpus for font sweeps, add a FONT_MATRIX entry with at least one FontVariant alongside the sources.json entry.","Keep sources.json and FONT_MATRIX keys consistent to avoid the [37]-vs-[38] ambiguity."],"tags":["cli","validation","config","corpus-font-matrix"],"backgroundTag":null,"analyzedSha":"ac49b09b7d83ede19581fa94a8b892b07d309baf","analyzedAt":"2026-08-12T17:03:16.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}