{"record":{"id":"2fdebc831416fc9c","repo":"denoland/deno","slug":"err-invalid-this-2fdebc","errorCode":"ERR_INVALID_THIS","errorMessage":"Value of \"this\" must be of type Event","messagePattern":"Value of \"this\" must be of type Event","errorType":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/event_target.mjs","lineNumber":131,"sourceCode":"      allowArray: true,\n      allowFunction: true,\n      nullable: true,\n    });\n    const { cancelable, bubbles, composed } = { ...options };\n    this[kCancelable] = !!cancelable;\n    this[kBubbles] = !!bubbles;\n    this[kComposed] = !!composed;\n    this[kType] = `${type}`;\n    this[kDefaultPrevented] = false;\n    this[kTimestamp] = performance.now();\n    this[kPropagationStopped] = false;\n    this[kTarget] = null;\n    this[kIsBeingDispatched] = false;\n  }\n\n  [customInspectSymbol](depth, options) {\n    if (!isEvent(this)) {\n      throw new ERR_INVALID_THIS(\"Event\");\n    }\n    const name = this.constructor.name;\n    if (depth < 0) {\n      return name;\n    }\n\n    const opts = ObjectAssign({}, options, {\n      depth: NumberIsInteger(options.depth) ? options.depth - 1 : options.depth,\n    });\n\n    return `${name} ${\n      inspect({\n        type: this[kType],\n        defaultPrevented: this[kDefaultPrevented],\n        cancelable: this[kCancelable],\n        timeStamp: this[kTimestamp],\n      }, opts)\n    }`;","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/event_target.mjs#L113-L149","documentation":"Event implements the nodejs.util.inspect.custom protocol used by util.inspect/console.log. That hook first verifies that its `this` is a genuine Event (constructed with the internal brand); when invoked on a foreign object it throws ERR_INVALID_THIS rather than reading missing internal slots. It fires when the custom-inspect method is extracted and called unbound, or when a non-Event object reaches inspect while carrying Event's prototype.","triggerScenarios":"Extracting and calling the hook directly: Event.prototype[Symbol.for('nodejs.util.inspect.custom')].call({}); passing the method as a callback: arr.map(ev[inspectKey]) so `this` is undefined; console.log on an object that mimics/shares Event.prototype without being constructed via new Event().","commonSituations":"Passing inspect methods around as first-class functions (lost binding); test doubles and mock libraries creating Event-like fakes by prototype assignment; adapters that borrow prototype methods to format arbitrary objects.","solutions":["Bind the hook when extracting: const show = ev[Symbol.for('nodejs.util.inspect.custom')].bind(ev)","Do not reuse Event's prototype methods to format foreign objects - write your own inspect function","Build test doubles as real Events (construct then mutate) instead of Object.create(Event.prototype)","If hit from console.log, find the object whose prototype chain includes Event.prototype but that was never constructed as an Event"],"exampleFix":"// before\nconst inspectKey = Symbol.for('nodejs.util.inspect.custom');\nconst show = ev[inspectKey];\nshow.call({}); // ERR_INVALID_THIS: Value of \"this\" must be of type Event\n\n// after\nconst show = ev[inspectKey].bind(ev);\nshow(); // renders the event","handlingStrategy":"try-catch","validationCode":"const INSPECT_KEY = Symbol.for('nodejs.util.inspect.custom');\nfunction inspectEvent(ev) {\n  if (!(ev instanceof Event)) throw new TypeError('inspectEvent expects an Event');\n  return ev[INSPECT_KEY].bind(ev)();\n}","typeGuard":"const isNodeEvent = (v) => v instanceof Event; // use before calling Event-only hooks","tryCatchPattern":"try {\n  text = inspect(obj);\n} catch (e) {\n  if (e?.code === 'ERR_INVALID_THIS') text = String(obj); // not a real Event; fall back\n  else throw e;\n}","preventionTips":["Bind methods extracted from objects before passing them as callbacks","Build test doubles as real constructed Events, not prototype clones","Never borrow Event's inspect hook to format foreign objects - write your own formatter"],"tags":["events","inspector","node-compat","this-binding"],"backgroundTag":"invalid-this","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}