{"record":{"id":"2ff3bfa2ac3df5f4","repo":"chenglou/pretext","slug":"step-must-be-0","errorCode":null,"errorMessage":"--step must be > 0","messagePattern":"--step must be > 0","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/corpus-font-matrix.ts","lineNumber":369,"sourceCode":"  }\n  return browser\n}\n\nasync function loadSources(): Promise<CorpusMeta[]> {\n  return await Bun.file('corpora/sources.json').json()\n}\n\nfunction parseOptions(): MatrixOptions {\n  const id = parseStringFlag('id')\n  if (id === null) {\n    throw new Error(`Missing --id. Available corpora: ${Object.keys(FONT_MATRIX).join(', ')}`)\n  }\n\n  const samples = parseOptionalNumberFlag('samples')\n  const start = parseNumberFlag('start', 300)\n  const end = parseNumberFlag('end', 900)\n  const step = parseNumberFlag('step', 10)\n  if (step <= 0) throw new Error('--step must be > 0')\n  if (end < start) throw new Error('--end must be >= --start')\n\n  return {\n    id,\n    browser: parseBrowser(parseStringFlag('browser')),\n    port: parseNumberFlag('port', Number.parseInt(process.env['CORPUS_CHECK_PORT'] ?? '0', 10)),\n    timeoutMs: parseNumberFlag('timeout', Number.parseInt(process.env['CORPUS_CHECK_TIMEOUT_MS'] ?? '180000', 10)),\n    output: parseStringFlag('output'),\n    samples,\n    start,\n    end,\n    step,\n  }\n}\n\nfunction getSweepWidths(meta: CorpusMeta, options: MatrixOptions): number[] {\n  const min = Math.max(options.start, meta.min_width ?? options.start)\n  const max = Math.min(options.end, meta.max_width ?? options.end)","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/chenglou/pretext/blob/ac49b09b7d83ede19581fa94a8b892b07d309baf/scripts/corpus-font-matrix.ts#L351-L387","documentation":"Thrown by parseOptions in corpus-font-matrix.ts after parsing the width-sweep bounds. --step is the pixel increment between sweep widths (default 10); it must be strictly positive or the loop would be infinite / degenerate. The check fires before the --end >= --start check, so an invalid step is reported first.","triggerScenarios":"parseNumberFlag('step', 10) returns a value <= 0. Throw on `--step=0`, `--step=-10`. Note `--step=0.5` parses as 0 via parseInt (no throw here, but produces an infinite loop downstream — parseInt's truncation turns a small positive into zero).","commonSituations":"Passing `--step=0` to mean \"every width\" (use 1 instead); negative steps from a sign error in a computed shell value; fractional steps (`0.5`) that parseInt silently floors to 0 — this is a footgun: the check does not catch it because the parse already happened upstream.","solutions":["Pass a positive integer step (default 10): `--step=10`, `--step=5`, `--step=1`.","Never pass a fractional step — parseInt will floor it before this check, and `--step=0.5` becomes 0 silently and would already have thrown at parseInt (it doesn't: parseInt('0.5') is 0, which then fails `step <= 0`).","If you need finer-than-1px resolution, that is not supported by the integer-width sweep model — extend getSweepWidths."],"exampleFix":"// before\nbun run scripts/corpus-font-matrix.ts --id=ja-kumo-no-ito --step=0\n// after\nbun run scripts/corpus-font-matrix.ts --id=ja-kumo-no-ito --step=10","handlingStrategy":"validation","validationCode":"function parseStep(raw: string | null): number {\n  const step = raw === null ? 10 : Number.parseInt(raw, 10)\n  if (!Number.isFinite(step) || step <= 0) {\n    throw new Error(`--step must be a positive integer, got ${JSON.stringify(raw)}`)\n  }\n  return step\n}","typeGuard":"function isPositiveInteger(value: string): boolean {\n  return /^\\d+$/.test(value) && Number.parseInt(value, 10) > 0\n}","tryCatchPattern":null,"preventionTips":["Pass a positive integer step (default 10).","Never pass fractional steps — parseInt floors them, turning 0.5 into 0 and tripping this check.","Use 1 for the finest sweep; 0 means \"no progress\" and is correctly rejected."],"tags":["cli","validation","args","corpus-font-matrix"],"backgroundTag":null,"analyzedSha":"ac49b09b7d83ede19581fa94a8b892b07d309baf","analyzedAt":"2026-08-12T17:03:16.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}