{"record":{"id":"aa3cffe02dc35a51","repo":"discordjs/discord.js","slug":"cannot-set-an-interval-greater-than-4-hours","errorCode":null,"errorMessage":"Cannot set an interval greater than 4 hours","messagePattern":"Cannot set an interval greater than 4 hours","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/rest/src/lib/REST.ts","lineNumber":94,"sourceCode":"\n\tpublic readonly options: RESTOptions;\n\n\tpublic constructor(options: Partial<RESTOptions> = {}) {\n\t\tsuper();\n\t\tthis.cdn = new CDN(options);\n\t\tthis.options = { ...DefaultRestOptions, ...options };\n\t\tthis.globalRemaining = Math.max(1, this.options.globalRequestsPerSecond);\n\t\tthis.agent = options.agent ?? null;\n\n\t\t// Start sweepers\n\t\tthis.setupSweepers();\n\t}\n\n\tprivate setupSweepers() {\n\t\t// eslint-disable-next-line unicorn/consistent-function-scoping\n\t\tconst validateMaxInterval = (interval: number) => {\n\t\t\tif (interval > 14_400_000) {\n\t\t\t\tthrow new Error('Cannot set an interval greater than 4 hours');\n\t\t\t}\n\t\t};\n\n\t\tif (this.options.hashSweepInterval !== 0 && this.options.hashSweepInterval !== Number.POSITIVE_INFINITY) {\n\t\t\tvalidateMaxInterval(this.options.hashSweepInterval);\n\t\t\tthis.hashTimer = setInterval(() => {\n\t\t\t\tconst sweptHashes = new Collection<string, HashData>();\n\t\t\t\tconst currentDate = Date.now();\n\n\t\t\t\t// Begin sweeping hash based on lifetimes\n\t\t\t\tthis.hashes.sweep((val, key) => {\n\t\t\t\t\t// `-1` indicates a global hash\n\t\t\t\t\tif (val.lastAccess === -1) return false;\n\n\t\t\t\t\t// Check if lifetime has been exceeded\n\t\t\t\t\tconst shouldSweep = Math.floor(currentDate - val.lastAccess) > this.options.hashLifetime;\n\n\t\t\t\t\t// Add hash to collection of swept hashes","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/discordjs/discord.js/blob/a81ed8a306d37fdc746e26a634b6a42164ba2c8c/packages/rest/src/lib/REST.ts#L76-L112","documentation":"REST's setupSweepers() enforces that the hashSweepInterval and handlerSweepInterval options never exceed 14,400,000 ms (4 hours). Intervals longer than that would let stale rate-limit hash data linger too long, so validateMaxInterval throws this Error at construction time if RESTOptions.hashSweepInterval exceeds the cap.","triggerScenarios":"Constructing `new REST({ hashSweepInterval: <value > 14_400_000 })` — e.g. 24 hours (86_400_000), Infinity (note: only exact Number.POSITIVE_INFINITY is exempted, any larger finite number throws), or a computed interval from config in seconds/minutes that wasn't converted to milliseconds correctly (e.g. passing 24 * 60 * 60 for hours as if seconds... or passing seconds where ms expected such as 50_000_000).","commonSituations":"Configuring sweep intervals in minutes/seconds but forgetting to multiply by 1000; copying hashLifetime (24h) into hashSweepInterval; trying to effectively disable sweeping with a huge number instead of 0 or Infinity.","solutions":["Lower hashSweepInterval to at most 14_400_000 (4 hours); the default is exactly 14_400_000, so simply omit the option.","To disable hash sweeping, set hashSweepInterval to 0 or Number.POSITIVE_INFINITY — those are the only exempt values.","Check unit conversion: values must be in milliseconds, so 4 hours = 4 * 60 * 60 * 1000.","Validate any config-driven interval with Math.min(interval, 14_400_000) before passing it to the REST constructor."],"exampleFix":"// before\nconst rest = new REST({ hashSweepInterval: 86_400_000 }); // throws: > 4 hours\n// after\nconst rest = new REST({ hashSweepInterval: Math.min(config.sweepMs, 14_400_000) });","handlingStrategy":"validation","validationCode":"const MAX_SWEEP_INTERVAL = 14_400_000;\nfunction assertSweepInterval(ms: number) {\n  if (ms !== 0 && ms !== Number.POSITIVE_INFINITY && ms > MAX_SWEEP_INTERVAL) {\n    throw new RangeError(`hashSweepInterval must be <= 4 hours (${MAX_SWEEP_INTERVAL} ms); got ${ms}`);\n  }\n}","typeGuard":"const isValidSweepInterval = (v: unknown): v is number =>\n  typeof v === 'number' && (v === 0 || v === Number.POSITIVE_INFINITY || (v > 0 && v <= 14_400_000));","tryCatchPattern":"try {\n  const rest = new REST({ hashSweepInterval: config.hashSweepMs });\n} catch (error) {\n  if (error.message.includes('greater than 4 hours')) {\n    logger.warn('hashSweepInterval too large, falling back to default');\n    rest = new REST();\n  } else {\n    throw error;\n  }\n}","preventionTips":["Remember intervals are in milliseconds — convert seconds/minutes before passing them in.","Use 0 or Number.POSITIVE_INFINITY (the only exempt values) to disable sweeping, never a huge finite number.","Clamp config values with Math.min(value, 14_400_000) at load time.","Keep the default (14_400_000) unless you have a specific reason to sweep more frequently."],"tags":["configuration","validation","rest-client","sweeper"],"backgroundTag":"invalid-config-value","analyzedSha":"a81ed8a306d37fdc746e26a634b6a42164ba2c8c","analyzedAt":"2026-08-30T04:07:22.193Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}