{"record":{"id":"5043442593e2a8e0","repo":"denoland/deno","slug":"err-illegal-constructor-504344","errorCode":"ERR_ILLEGAL_CONSTRUCTOR","errorMessage":"Illegal constructor","messagePattern":"Illegal constructor","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/timers.ts","lineNumber":371,"sourceCode":"\nconst promises = {\n  setTimeout: setTimeoutPromise,\n  setImmediate: setImmediatePromise,\n  setInterval: setIntervalAsync,\n};\n\n// There is exactly one `scheduler`, so identity is the check: a\n// prototype-linked object, or one carrying whatever properties the real\n// instance has, is still a foreign receiver.\nfunction validateScheduler(self: unknown) {\n  if (self !== scheduler) {\n    throw new ERR_INVALID_THIS(\"Scheduler\");\n  }\n}\n\nclass Scheduler {\n  constructor() {\n    throw new ERR_ILLEGAL_CONSTRUCTOR();\n  }\n  // Not `async`: the `this` check has to reject a foreign receiver\n  // synchronously rather than returning a rejected promise.\n  wait(\n    delay: number,\n    options?: { signal?: AbortSignal },\n  ): Promise<void> {\n    validateScheduler(this);\n    return setTimeoutPromise(delay, undefined, options);\n  }\n  yield() {\n    validateScheduler(this);\n    return promises.setImmediate();\n  }\n}\n\nconst scheduler = ObjectCreate(Scheduler.prototype);\npromises.scheduler = scheduler;","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/timers.ts#L353-L389","documentation":"The Scheduler class exported by node:timers implements the Scheduling API, but there is exactly one scheduler per realm: Node and this Deno polyfill both make `new Scheduler()` throw ERR_ILLEGAL_CONSTRUCTOR. The class is exported only for identity checks such as `scheduler instanceof Scheduler`. All functionality lives on the exported `scheduler` singleton, whose methods also reject foreign `this` values with ERR_INVALID_THIS.","triggerScenarios":"Executing `new Scheduler()` after importing it from node:timers; instantiating a subclass (`class S extends Scheduler {}` then `new S()`); calling `Scheduler.prototype.wait.call({}, 100)`; test utilities that enumerate module exports and try to construct every class.","commonSituations":"Porting scheduling code written against a constructible API; attempting per-request or per-test scheduler instances for isolation; mocking node:timers by subclassing Scheduler.","solutions":["Use the exported singleton: `import { scheduler } from 'node:timers'` and call `scheduler.wait(ms)` or `scheduler.yield()`","For dependency injection or tests, wrap the singleton in your own function instead of subclassing Scheduler","Keep importing Scheduler only for `instanceof` assertions","Use timers/promises `setTimeout(ms)` when you only need a delayable promise"],"exampleFix":"// before\nimport { Scheduler } from \"node:timers\";\nconst s = new Scheduler(); // ERR_ILLEGAL_CONSTRUCTOR\nawait s.wait(100);\n\n// after\nimport { scheduler } from \"node:timers\";\nawait scheduler.wait(100);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"import { scheduler } from \"node:timers\";\nconst isScheduler = (v: unknown): v is typeof scheduler => v === scheduler;","tryCatchPattern":"try {\n  await runLibrary(opts); // may construct Scheduler internally\n} catch (e: any) {\n  if (e?.code === \"ERR_ILLEGAL_CONSTRUCTOR\") {\n    await scheduler.wait(opts.delay); // use the singleton instead\n  } else {\n    throw e;\n  }\n}","preventionTips":["Never call new on the exported Scheduler class; it exists for instanceof checks only","Route all waits through the imported scheduler singleton","For testability, inject a wait function rather than constructing schedulers","Borrowed scheduler methods also throw ERR_INVALID_THIS on foreign receivers"],"tags":["node-compat","timers","scheduler","constructor"],"backgroundTag":"illegal-constructor","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}