{"record":{"id":"1aa6cee88ea4f0a5","repo":"denoland/deno","slug":"illegal-invocation","errorCode":null,"errorMessage":"Illegal invocation","messagePattern":"Illegal invocation","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/_tls_common.ts","lineNumber":636,"sourceCode":"      ca: useDefaultCA ? undefined : normalizeCertValue(effectiveCa),\n      useDefaultCA,\n      cert: normalizeCertPem(options.cert) ?? pfxCert,\n      key: normalizeKeyPem(options.key, options.passphrase) ?? pfxKey,\n      minVersion,\n      maxVersion,\n      ciphers: options.ciphers,\n      passphrase: options.passphrase,\n      sigalgs: options.sigalgs,\n      ecdhCurve: options.ecdhCurve,\n    };\n    secureContextBrand.add(this.context);\n    ObjectDefineProperty(this.context, \"_external\", {\n      __proto__: null,\n      configurable: true,\n      enumerable: false,\n      get(this: object) {\n        if (!WeakSetPrototypeHas(secureContextBrand, this)) {\n          throw new TypeError(\"Illegal invocation\");\n        }\n        return this;\n      },\n    });\n    (this.context as any).setOptions = function setOptions(\n      this: object,\n      _options?: number,\n    ) {\n      if (!WeakSetPrototypeHas(secureContextBrand, this)) {\n        throw new TypeError(\"Illegal invocation\");\n      }\n    };\n    (this.context as any).addCACert = function addCACert(\n      this: any,\n      cert: any,\n    ) {\n      if (!WeakSetPrototypeHas(secureContextBrand, this)) {\n        throw new TypeError(\"Illegal invocation\");","sourceCodeStart":618,"sourceCodeEnd":654,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/_tls_common.ts#L618-L654","documentation":"The internal SecureContext object returned by tls.createSecureContext installs an _external property whose getter only works when called on an object branded via a private WeakSet (ext/node/polyfills/_tls_common.ts:636). Calling the getter with a tampered this — via .call(), Reflect.get with a receiver, or a detached getter — throws TypeError('Illegal invocation'), the same WebIDL-style brand check browsers use.","triggerScenarios":"Reflect.get(ctx, '_external', someOtherObject), Object.getOwnPropertyDescriptor(ctx, '_external').get.call({}), or destructuring the property off a Proxy that forwards the receiver. Normal property reads like ctx._external never throw.","commonSituations":"Test suites or mocking libraries (sinon, test spies) that grab property descriptors and invoke getters with a stub receiver; code that copies accessors between objects with Object.assign on the descriptor level; deep-clone tools that re-invoke getters.","solutions":["Read the property normally (ctx._external) instead of extracting the getter and changing its receiver","If you extracted the descriptor, invoke it bound to the original object: const d = Object.getOwnPropertyDescriptor(ctx, '_external'); d.get.call(ctx)","In mocks/spies, wrap the original object rather than re-binding its accessors to a fake this"],"exampleFix":"// before\nconst desc = Object.getOwnPropertyDescriptor(ctx, '_external');\nconst ext = desc.get.call(myFakeThis); // TypeError\n\n// after\nconst ext = ctx._external; // brand check passes","handlingStrategy":"validation","validationCode":"// Never extract the getter; read the property on the branded object only.\nconst ext = ctx._external;","typeGuard":null,"tryCatchPattern":"try { Reflect.get(target, '_external', receiver); } catch (e) { if (e instanceof TypeError && e.message === 'Illegal invocation') receiver = target; /* retry with correct receiver */ else throw e; }","preventionTips":["Avoid Reflect.get with a custom receiver on foreign objects","In mocks, wrap whole objects instead of rebinding accessors"],"tags":["tls","typeerror","brand-check","internal-api"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}