{"record":{"id":"e273d0f7f3982092","repo":"chenglou/pretext","slug":"failed-to-measure-currentmeta-id-corpus","errorCode":null,"errorMessage":"Failed to measure ${currentMeta?.id ?? 'corpus'} @ ${width}","messagePattern":"Failed to measure (.+?) @ (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pages/corpus.ts","lineNumber":956,"sourceCode":"              reasonGuess: report.firstBreakMismatch.reasonGuess,\n              oursContext: report.firstBreakMismatch.oursContext,\n              browserContext: report.firstBreakMismatch.browserContext,\n            },\n          }),\n  }\n}\n\nfunction runSweep(widths: number[]): void {\n  if (currentMeta === null || currentPrepared === null) {\n    return\n  }\n\n  const font = buildFont(currentMeta)\n  const lineHeight = getLineHeight(currentMeta)\n  const rows = widths.map(width => {\n    const report = measureWidth(width, { publish: false, updateStats: false })\n    if (report === null || report.status === 'error') {\n      throw new Error(report?.message ?? `Failed to measure ${currentMeta?.id ?? 'corpus'} @ ${width}`)\n    }\n    return toSweepRow(report)\n  })\n  const exactCount = rows.filter(row => Math.round(row.diffPx) === 0).length\n\n  stats.textContent =\n    `${currentMeta.title} | Sweep: ${exactCount}/${rows.length} exact | ${rows.length - exactCount} nonzero` +\n    ` | ${currentText.length.toLocaleString()} chars`\n\n  setReport(withRequestId({\n    status: 'ready',\n    environment: getEnvironmentFingerprint(),\n    corpusId: currentMeta.id,\n    sliceStart: currentSliceStart,\n    sliceEnd: currentSliceEnd,\n    title: currentMeta.title,\n    language: currentMeta.language,\n    direction: getDirection(currentMeta),","sourceCodeStart":938,"sourceCodeEnd":974,"githubUrl":"https://github.com/chenglou/pretext/blob/ac49b09b7d83ede19581fa94a8b892b07d309baf/pages/corpus.ts#L938-L974","documentation":"Thrown inside runSweep() after calling measureWidth(width, { publish: false, updateStats: false }) for each width in the sweep. If measureWidth returns null (no prepared text available) or returns a report with status === 'error', the sweep cannot continue and this throw fires — preferring report.message when present and falling back to the 'Failed to measure ... @ width' template only when report is null. It halts the entire multi-width sweep, so partial rows already computed are discarded.","triggerScenarios":"measureWidth returns an error-status report because the diagnostic canvas/div could not be measured (e.g. zero-size viewport, font not ready, prepared segments missing), or returns null because currentPrepared/currentMeta were cleared between the runSweep guard at line 947 and the map callback. Most often the underlying cause is a measurement-time exception inside measureWidth that got caught and converted to an error report.","commonSituations":"Running a corpus sweep very early before document.fonts.ready resolves; a font override (?font=) pointing at a family that is not installed so canvas measurement yields garbage; an extremely narrow width where the engine and browser disagree and measureWidth's internal consistency check fails; concurrent reinitialization while a sweep is in flight.","solutions":["Open the same corpus at a single width (?width=) to reproduce the underlying measureWidth error and read its message — the fallback template only appears when report is null.","Ensure fonts are loaded before triggering the sweep; the loadCorpus flow already awaits document.fonts.ready, so avoid invoking runSweep manually before init completes.","Remove the ?font= / ?lineHeight= overrides to confirm the failure is font-specific.","If automating, increase ACCURACY_CHECK_TIMEOUT_MS and retry — transient measurement races on slow machines can surface here."],"exampleFix":"// before\nconst report = measureWidth(width, { publish: false, updateStats: false })\nif (report === null || report.status === 'error') {\n  throw new Error(report?.message ?? `Failed to measure ${currentMeta?.id ?? 'corpus'} @ ${width}`)\n}\n\n// after (collect failures instead of aborting the whole sweep)\nconst report = measureWidth(width, { publish: false, updateStats: false })\nif (report === null || report.status === 'error') {\n  failedWidths.push({ width, message: report?.message ?? `Failed to measure @ ${width}` })\n  return null\n}\nreturn toSweepRow(report)","handlingStrategy":"try-catch","validationCode":"// Before a sweep, confirm measurement is viable at a single width.\nfunction canSweep(): boolean {\n  return currentMeta !== null && currentPrepared !== null && currentText.length > 0\n}\nif (!canSweep()) {\n  // skip the sweep\n}","typeGuard":"function isReadyReport(report: ReturnType<typeof measureWidth>): report is NonNullable<typeof report> & { status: 'ready' } {\n  return report !== null && report.status === 'ready'\n}","tryCatchPattern":"// Wrap runSweep so one bad width does not abort the whole sweep.\nconst failed: Array<{ width: number, message: string }> = []\nconst rows = widths.flatMap(width => {\n  const report = measureWidth(width, { publish: false, updateStats: false })\n  if (report === null || report.status === 'error') {\n    failed.push({ width, message: report?.message ?? `Failed @ ${width}` })\n    return []\n  }\n  return [toSweepRow(report)]\n})\nif (failed.length > 0) console.warn('Sweep failures:', failed)","preventionTips":["Ensure document.fonts.ready has resolved before triggering a sweep (loadCorpus already does this).","Validate the ?font= override resolves to an installed family before sweeping.","When automating, probe a single width first; only sweep once a single-width measurement succeeds."],"tags":["corpus-page","measurement","sweep","canvas"],"backgroundTag":null,"analyzedSha":"ac49b09b7d83ede19581fa94a8b892b07d309baf","analyzedAt":"2026-08-12T17:03:16.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}