-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
err: TypeError: Client request error: Cannot read private member #context from an object whose class did not declare it #305
Comments
Point of clarity: The error itself is generated by NodeJS and appears to be triggered by something in its internal URL library. But normal usage of that library is fine. This error only turns up for us when going via wreck. We're trying to work out what's special about this call. |
@KrayzeeKev I'm failing to reproduce this. I'm running the example from the docs: const Wreck = require('@hapi/wreck');
const example = async function () {
const { res, payload } = await Wreck.get('http://example.com');
console.log(payload.toString());
};
try {
example();
}
catch (ex) {
console.error(ex);
} And it works without errors on when using Node.js v20.9.0 on MacOS, at least when installing it fresh so that the "node_modules/@hapi/boom": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-10.0.1.tgz",
"integrity": "sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==",
"dependencies": {
"@hapi/hoek": "^11.0.2"
}
},
"node_modules/@hapi/bourne": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-3.0.0.tgz",
"integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w=="
},
"node_modules/@hapi/hoek": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.2.tgz",
"integrity": "sha512-aKmlCO57XFZ26wso4rJsW4oTUnrgTFw2jh3io7CAtO9w4UltBNwRXvXIVzzyfkaaLRo3nluP/19msA8vDUUuKw=="
},
"node_modules/@hapi/wreck": {
"version": "18.0.1",
"resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-18.0.1.tgz",
"integrity": "sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg==",
"dependencies": {
"@hapi/boom": "^10.0.1",
"@hapi/bourne": "^3.0.0",
"@hapi/hoek": "^11.0.2"
}
} Considering that And the tests passes in general for this module, so maybe |
@KrayzeeKev Can you specify which version of |
There is one test that fails on Windows starting with Node 18:
But that appears to not be the same, though shows that OS can be of importance here |
simple-oauth2 5.0.0 I believe I've narrowed it down some more and @Hapi may be off the hook:
It's definitely the proxy agent. Axios via the proxy seems happy so it's something HttpsProxyAgent is doing. I will investigate further and see if it's purely that module or if it's the way these 3 modules (wreck, simple-oauth2, https-proxy-agent) interact. Thanks for you assistance so far. |
Found it. It's @hapi/hoek/lib/clone as used by @hapi/hoek/lib/applyToDefaults as used by Wreck
I've read elsewhere that the nature of private variables (used in the URL class/object in this case, for instance) means that you can't wrap them in a Proxy without doing some trickery. I wonder if this is related. I have a nodejs issue open similarly here and I will update that with this minimal case. The story about the Proxy implied this was by design so that would mean that the @hapi/hoek clone needs a new special case or something. Here's the SO article: https://stackoverflow.com/questions/67416881/es6-proxied-class-access-private-property-cannot-read-private-member-hidden-f |
The following comments are from Jordan Harband - TC39 (JS standards body) member, contributor to NodeJS, author of npm - on slack
Since wreck may know the full list of possible config options it can get passed, it might be possible to explicitly check for URL in the hoek/clone. It's ugly but there does not seem to be any other choice other than giving up on the deep clone. |
Thanks for the investigation! This is just an another special object case for |
Thanks. Now I just have to hope that all the semvers along the way mean I'll get the latest because the module I'm using directly was last updated 12 months ago. |
Still not 100% sure why wreck needs to deep clone its config params at all. Are callers really keeping references to sub objects and modifying them or something? |
Some cloning could historically be helpful, especially in a pre-typed world, where it could avoid tricky bugs where a changed value in one part of the code propagated into another part of the code as one were accidentally modifying the very same object Now it can be better to prohibit that by typing those options with Another alternative nowadays can be Ideally one shouldn’t have a deep nested configuration object and thus don’t need deep cloning but rather be able to achieve one’s need through eg simple destructuring |
Eg: Associative arrays in PHP are not sent as references to the same associative array but rather sent as a copy of the values, so if one wants to mimic eg. that style in JS then one has to do copy the values oneself, like seems to be done here |
I'm not seeing any modification to the |
@Marsup Would that make it so that wreck tells hoek not to clone it? |
We use the clone to guard against subsequent manipulation by the caller. Eg. const baseUrl = new URL('https://hapi.dev/');
const wreck = Wreck.defaults({ baseUrl });
baseUrl.hostname = 'google.com';
await wreck.get('/api/'); Without the clone, this would request from It is a general principle in the hapi ecosystem to clone passed options when used async. This eliminates a class of hard to debug problems, when users inadvertently modify a passed property after calling the method. |
@kanongil One can achieve that without using a generic deep clone though? |
@KrayzeeKev new hoek version is released as |
Runtime
NodeJS
Runtime version
v20
Module version
18.0.1
Last module version without issue
No response
Used with
simple-oauth2
Any other relevant information
Can not work out if this is a wreck issue or a nodejs issue. Or perhaps even a simple-oauth2 problem.
What are you trying to achieve or the steps to reproduce?
Using simple-oauth2 to get a token and that modules uses @hapi/wreck
simple-oauth2 does nothing more than this:
this.#client = Wreck.defaults(httpOptions);
const response = await this.#client.post(url, options);
where url is a string.
It feels like something wreck is doing is triggering the NodeJS internal url library to try do something weird although I can't see how an external library like wreck could be doing anything so bad as to cause such an issue. I am pretty certain this is a NodeJS issue but something special is happening here because it's unfathomable that v20.10 has come along and nobody usin
What was the result you got?
err: TypeError: Client request error: Cannot read private member #context from an object whose class did not declare it
I added a
console.log(new Error().stack))
to on Error and got this - not particularly informative:Error
at ClientRequest.onError (/opt/APP/node_modules/@hapi/wreck/lib/index.js:192:13)
at Object.onceWrapper (node:events:629:26)
at ClientRequest.emit (node:events:514:28)
at _destroy (node:_http_client:875:13)
at onSocketNT (node:_http_client:895:5)
at process.processTicksAndRejections (node:internal/process/task_queues:83:21)
2023-11-20T09:41:01+11:00 [ERROR] - Failed to Get Token - err: TypeError: Client request error: Cannot read private member #context from an object whose class did not declare it
The actual error is thrown in
lib/internal/url.js
which is new to NodeJS v20. I've raised nodejs/node#50891 against NodeJs to try get at this from both directions but it's strange we've got to v20.10 and nobody else is experiencing this. It happens in v20.0 (which is when url.js got introduced).What result did you expect?
No error :-)
The text was updated successfully, but these errors were encountered: