{"record":{"id":"4d41725b4c60822c","repo":"denoland/deno","slug":"err-construct-call-required-4d4172","errorCode":"ERR_CONSTRUCT_CALL_REQUIRED","errorMessage":"Class constructor MessageChannel cannot be invoked without `new`","messagePattern":"Class constructor MessageChannel cannot be invoked without `new`","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/worker_threads.ts","lineNumber":1878,"sourceCode":"  }\n  port[MessagePortReceiveMessageOnPortSymbol] = true;\n  const portId = getMessagePortId(port);\n  if (portId === null) return undefined;\n  const data = op_message_port_recv_message_sync(portId);\n  if (data === null) return undefined;\n  const message = deserializeJsMessageData(data)[0];\n  patchMessagePortIfFound(message);\n  return { message };\n}\n\n// Implemented as a function (not a class) so calling without `new` throws\n// our Node-style `ERR_CONSTRUCT_CALL_REQUIRED` instead of V8's default\n// \"Class constructor X cannot be invoked without 'new'\" -- the node_compat\n// suite asserts the specific code/constructor for both forms.\n// deno-lint-ignore no-explicit-any\nfunction NodeMessageChannel(this: any) {\n  if (new.target === undefined) {\n    throw new ERR_CONSTRUCT_CALL_REQUIRED(\"MessageChannel\");\n  }\n  {\n    const channel = new MessageChannel();\n    const port1 = webMessagePortToNodeMessagePort(channel.port1);\n    const port2 = webMessagePortToNodeMessagePort(channel.port2);\n    // The web MessageChannel.prototype defines port1/port2 as getter-only\n    // accessors, so a plain `this.port1 = ...` triggers a setter trap. Use\n    // defineProperty to shadow the prototype accessors with own data\n    // properties that hold our Node-style ports.\n    ObjectDefineProperty(this, \"port1\", {\n      __proto__: null,\n      value: port1,\n      writable: true,\n      enumerable: true,\n      configurable: true,\n    });\n    ObjectDefineProperty(this, \"port2\", {\n      __proto__: null,","sourceCodeStart":1860,"sourceCodeEnd":1896,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/worker_threads.ts#L1860-L1896","documentation":"worker_threads' MessageChannel is deliberately implemented as a function whose body throws Node's ERR_CONSTRUCT_CALL_REQUIRED('MessageChannel') when invoked without new — reproducing Node's error code and constructor identity instead of V8's generic class-constructor message. The node_compat suite asserts both the code and the constructor for the called-without-new and normal forms.","triggerScenarios":"MessageChannel(); MessageChannel.call({}); MessageChannel.apply(null, []); passing MessageChannel directly as a callback (arr.map(MessageChannel)) so it is invoked unbound.","commonSituations":"Older factory-style code; transpilers or bundlers rewriting classes; passing constructors as callbacks; snippets predating ES classes.","solutions":["Always use new: const { port1, port2 } = new MessageChannel().","Wrap when passing as a callback: () => new MessageChannel().","Enable TypeScript — calling a class-typed constructor without new is a compile error."],"exampleFix":"// before\nconst channel = MessageChannel();\n\n// after\nconst channel = new MessageChannel();\nconst { port1, port2 } = channel;","handlingStrategy":"try-catch","validationCode":"function makeChannel(): MessageChannel {\n  return new MessageChannel(); // single construction path, always with new\n}\nconst { port1, port2 } = makeChannel();","typeGuard":null,"tryCatchPattern":"let channel: MessageChannel;\ntry {\n  channel = (MessageChannel as unknown as () => MessageChannel)();\n} catch (e) {\n  if (e?.code === 'ERR_CONSTRUCT_CALL_REQUIRED') channel = new MessageChannel();\n  else throw e;\n}","preventionTips":["Route all channel creation through one factory that uses new.","Let TypeScript flag bad call sites — constructor types reject the call form.","Code-review .map/.from callbacks that receive constructors directly."],"tags":["worker-threads","messagechannel","constructor","node-compat"],"backgroundTag":"constructor-without-new","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}