{"record":{"id":"e46d66f8273203c6","repo":"agalwood/Motrix","slug":"label-must-be-a-safe-integer-timestamp","errorCode":null,"errorMessage":"${label} must be a safe integer timestamp","messagePattern":"(.+?) must be a safe integer timestamp","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"src/core/lib/sqlite-integers.ts","lineNumber":38,"sourceCode":"    throw new RangeError(`${label} exceeds the JavaScript safe integer range`)\n  }\n  return Number(value)\n}\n\nexport function nonNegativeIntegerFromBigInt(\n  value: bigint,\n  label: string\n): number {\n  const converted = safeIntegerFromSql(value, label)\n  if (converted < 0) {\n    throw new RangeError(`${label} must be non-negative`)\n  }\n  return converted\n}\n\nexport function requireSafeTimestamp(value: number, label: string): void {\n  if (!Number.isSafeInteger(value)) {\n    throw new RangeError(`${label} must be a safe integer timestamp`)\n  }\n}\n\nexport function requireSafePositiveTimestamp(\n  value: number,\n  label: string\n): void {\n  if (!Number.isSafeInteger(value) || value <= 0) {\n    throw new RangeError(`${label} must be a positive safe integer timestamp`)\n  }\n}\n","sourceCodeStart":20,"sourceCodeEnd":50,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/lib/sqlite-integers.ts#L20-L50","documentation":"Thrown by requireSafeTimestamp when a numeric value is not a safe integer. This is a guard used at trust boundaries (inputs, persisted timestamps) to reject NaN, Infinity, fractional seconds, or values beyond 2^53 before they reach time arithmetic.","triggerScenarios":"Calling requireSafeTimestamp(value, label) where value is NaN (e.g. Number(undefined)), a float like 1700000000.5, Infinity, or a millisecond timestamp accidentally treated as seconds that exceeds the safe range.","commonSituations":"Mixing seconds and milliseconds epoch units; parsing a timestamp from an untrusted API that returned a string (Number('N/A') = NaN); floating-point division that introduced a fractional component.","solutions":["Coerce and unit-normalize the value before calling the guard (e.g. Math.trunc, divide/multiply by 1000 as needed).","Validate the upstream source returned a finite integer string before Number()-ing it.","If fractional seconds are intended, switch to a storing scheme that keeps whole-second precision.","Log the raw input alongside the label to find which field is malformed."],"exampleFix":"// before\nrequireSafeTimestamp(Number(req.query.t), 't')\n// after\nconst t = Number(req.query.t)\nif (!Number.isFinite(t)) throw new TypeError('bad t')\nrequireSafeTimestamp(Math.trunc(t), 't')","handlingStrategy":"validation","validationCode":"function isSafeTimestamp(value: unknown): value is number {\n  return typeof value === 'number' && Number.isSafeInteger(value)\n}\nif (!isSafeTimestamp(input.t)) {\n  throw new TypeError(`t must be a safe integer; got ${input.t}`)\n}\nrequireSafeTimestamp(input.t, 't')","typeGuard":"function isSafeTimestamp(value: unknown): value is number {\n  return typeof value === 'number' && Number.isSafeInteger(value)\n}","tryCatchPattern":"try {\n  requireSafeTimestamp(t, 't')\n} catch (e) {\n  if (e instanceof RangeError) {\n    // reject the input payload rather than crashing\n  } else throw e\n}","preventionTips":["Normalise incoming timestamps with Math.trunc and an explicit seconds-vs-milliseconds decision before validation.","Validate untrusted API payloads with a schema (zod/json-schema) before they reach the guard.","Log the raw input value when validation fails so the source of NaN/Infinity is traceable."],"tags":["timestamp","validation","type-coercion"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}