{"record":{"id":"c1d750953fb09342","repo":"upstash/context7","slug":"timeout-must-be-a-positive-number-or-false","errorCode":null,"errorMessage":"timeout must be a positive number or false","messagePattern":"timeout must be a positive number or false","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/sdk/src/http/abort.ts","lineNumber":11,"sourceCode":"import { Context7Error } from \"@error\";\n\nexport type AbortState = {\n  signal?: AbortSignal;\n  timedOut: () => boolean;\n  cleanup: () => void;\n};\n\nexport function validateTimeout(timeout: number | false): void {\n  if (timeout !== false && (!Number.isFinite(timeout) || timeout <= 0)) {\n    throw new TypeError(\"timeout must be a positive number or false\");\n  }\n}\n\nexport function resolveSignal(signal?: AbortSignal | (() => AbortSignal)): AbortSignal | undefined {\n  return typeof signal === \"function\" ? signal() : signal;\n}\n\nexport function createAbortState(\n  signals: Array<AbortSignal | undefined>,\n  timeout: number | false\n): AbortState {\n  validateTimeout(timeout);\n\n  const activeSignals = [\n    ...new Set(signals.filter((signal): signal is AbortSignal => signal !== undefined)),\n  ];\n  if (timeout === false && activeSignals.length === 0) {\n    return { timedOut: () => false, cleanup: () => undefined };","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/upstash/context7/blob/80e681a507c5287bc12e483367c40754e29461b9/packages/sdk/src/http/abort.ts#L1-L29","documentation":"TypeError thrown by validateTimeout when the `timeout` option is neither `false` (disabled) nor a positive finite number. The SDK requires timeout to be a millisecond value > 0 or explicitly false to disable it.","triggerScenarios":"Constructing a Context7 client (or calling createAbortState) with timeout: 0, timeout: -1000, timeout: Infinity, timeout: NaN, or a non-number truthy value like a string \"5000\" that is not false.","commonSituations":"Loading timeout from environment variables or config files as a string (\"5000\"), computing it to 0 or NaN via parsing, or intending to disable it with 0 instead of false.","solutions":["Pass a positive finite number of milliseconds, e.g. timeout: 10000.","To disable the timeout entirely, pass timeout: false, not 0.","If loading from env/config, coerce and validate: Number.isFinite(v) && v > 0 before constructing the client.","Use Number(rawValue) and guard against NaN when parsing user-supplied values."],"exampleFix":"// before\nconst client = new Context7Client({ timeout: Number(process.env.TIMEOUT) }); // NaN -> TypeError\n// after\nconst t = Number(process.env.TIMEOUT);\nconst client = new Context7Client({ timeout: Number.isFinite(t) && t > 0 ? t : false });","handlingStrategy":"validation","validationCode":"function assertTimeout(t: unknown): asserts t is number | false {\n  if (!(t === false || (typeof t === 'number' && Number.isFinite(t) && t > 0))) {\n    throw new TypeError(`timeout must be a positive number or false, got ${String(t)}`);\n  }\n}","typeGuard":"function isValidTimeout(t: unknown): t is number | false {\n  return t === false || (typeof t === 'number' && Number.isFinite(t) && t > 0);\n}","tryCatchPattern":"try {\n  const client = new Context7Client({ timeout: parsedTimeout });\n} catch (e) {\n  if (e instanceof TypeError && /timeout/.test(e.message)) {\n    console.error('Bad timeout config, falling back to default');\n  }\n  throw e;\n}","preventionTips":["Never pass 0 to disable a timeout; use false.","Coerce env/config values with Number() and check Number.isFinite.","Centralize timeout parsing in one validated helper."],"tags":["configuration","validation","typescript"],"backgroundTag":"invalid-config-value","analyzedSha":"80e681a507c5287bc12e483367c40754e29461b9","analyzedAt":"2026-09-08T05:18:41.043Z","contentChangedAt":"2026-09-08T05:18:41.043Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}