{"record":{"id":"8a198d31a5f64f2a","repo":"tobi/qmd","slug":"timeout-must-be-a-non-negative-number-of-minutes","errorCode":null,"errorMessage":"--timeout must be a non-negative number of minutes (0 = no limit)","messagePattern":"--timeout must be a non-negative number of minutes \\(0 = no limit\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/qmd.ts","lineNumber":2109,"sourceCode":"    throw new Error(`${name} must be a positive integer`);\n  }\n  return parsed;\n}\n\nfunction parseChunkStrategy(value: unknown): ChunkStrategy | undefined {\n  if (value === undefined) return undefined;\n  const s = String(value);\n  if (s === \"auto\" || s === \"regex\") return s;\n  throw new Error(`--chunk-strategy must be \"auto\" or \"regex\" (got \"${s}\")`);\n}\n\n// --timeout for `qmd embed`: a cap on the whole embed session, in minutes. Returns\n// the value in milliseconds, or undefined to use the default. 0 disables the cap.\nfunction parseEmbedTimeoutOption(value: unknown): number | undefined {\n  if (value === undefined) return undefined;\n  const minutes = Number(value);\n  if (!Number.isFinite(minutes) || minutes < 0) {\n    throw new Error(`--timeout must be a non-negative number of minutes (0 = no limit)`);\n  }\n  return minutes * 60 * 1000;\n}\n\nfunction ensureModelsConfiguredForCli(): { embed: string; generate: string; rerank: string } {\n  try {\n    const config = loadConfig();\n    const models = resolveModels(config.models);\n    const current = config.models ?? {};\n    if (current.embed !== models.embed || current.generate !== models.generate || current.rerank !== models.rerank) {\n      saveConfig({\n        ...config,\n        models: {\n          ...current,\n          embed: models.embed,\n          generate: models.generate,\n          rerank: models.rerank,\n        },","sourceCodeStart":2091,"sourceCodeEnd":2127,"githubUrl":"https://github.com/tobi/qmd/blob/dbfd0b4736aeaf761d1a16ca8e424f071df8feb9/src/cli/qmd.ts#L2091-L2127","documentation":"Thrown by parseEmbedTimeoutOption when `qmd embed --timeout` receives a value that is not a finite non-negative number of minutes. The timeout caps the whole embed session; 0 means no limit, negative or non-numeric values are rejected.","triggerScenarios":"Running `qmd embed --timeout -5`, `--timeout abc`, or passing an empty-string variable from a shell script; passing seconds (e.g. 3600) which yields an absurdly large but technically valid value.","commonSituations":"Script variables unset/empty; unit confusion (assuming seconds or milliseconds); typo'd numbers.","solutions":["Pass minutes as a non-negative number: `qmd embed --timeout 30`","Use 0 to disable the cap: `qmd embed --timeout 0`","Default shell variables in scripts: `--timeout \"${TIMEOUT:-10}\"`"],"exampleFix":"# before\nqmd embed --timeout 3600\n# after\nqmd embed --timeout 60","handlingStrategy":"type-guard","validationCode":"const m = Number(v);\nif (!Number.isFinite(m) || m < 0) throw new RangeError('--timeout must be >= 0 minutes');","typeGuard":"const isValidTimeout = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v) && v >= 0;","tryCatchPattern":null,"preventionTips":["The unit is minutes, not seconds/ms","Use --timeout 0 for unlimited; default empty variables in scripts"],"tags":["cli","embed","option-validation"],"backgroundTag":"invalid-cli-argument","analyzedSha":"dbfd0b4736aeaf761d1a16ca8e424f071df8feb9","analyzedAt":"2026-08-28T18:07:46.628Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}