-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
More useful error than toString failed
when Buffer length greater than kMaxLength?
#3175
Comments
256 MB is the limit for strings in V8 so no, it's not a regression. What would you report in more detail? |
Anything would be better than that TBH. |
It's not obvious to the user what's actually gone wrong. How about "Cannot create string larger than 256MB"? Seems a lot clearer to me. |
I think a pull request to that effect would be acceptable. |
But is that the only error that can occur? Looking at the code at the moment, the check is pretty basic – is there no way of getting more detail as to why |
Not at the moment, no. The undefined value trickles down from StringBytes::Encode() in src/string_bytes.h. I don't think there are other code paths that return an empty |
FWIW, v8 (I assume?) spits out a slightly better error when trying to concat strings: $ node -p 'var a = "a"; for (var i = 0; i < 27; i++) a = a + a; a.length'
134217728
$ node -p 'var a = "a"; for (var i = 0; i < 28; i++) a = a + a; a.length'
[eval]:1
var a = "a"; for (var i = 0; i < 28; i++) a = a + a; a.length
^
RangeError: Invalid string length
at [eval]:1:49
at Object.exports.runInThisContext (vm.js:54:17)
at Object.<anonymous> ([eval]-wrapper:6:22)
at Module._compile (module.js:434:26)
at node.js:566:27
at doNTCallback0 (node.js:407:9)
at process._tickCallback (node.js:336:13) Is the size limit exposed at all? If it were I'd be happy to add a PR that checks, in the case of an |
I don't think it is exposed in JS. The exact limit is Line 2083 in 64beab0
|
toString failed
?toString failed
when Buffer length greater than kMaxLength?
I would love to take a stab at this if people are open to it. /cc @jasnell |
Works for me!
|
@MylesBorins Seems the discussion addresses more than just the error message. Mind identifying the specifics of what you'll be working on? |
I specifically was interested in a better error message when toString is called on a Buffer larger than kStringMaxLength That seemed like a pretty easy one to knock out (I've basically got it done already). |
@MylesBorins I think the discussion was around how to detect the limit though – have you exposed |
I mean, the code comments in v8.h for |
I take back what I said about having this done. I was hard coding the size, which in retrospect is not robust enough. |
@mhart I don't suggest attempting to pre-detect the limit. Let v8 try and it will return whether it could or not. It's both more future proof and allows limitations on system resources to also return undefined. @MylesBorins Improving the error message is a good place to start. |
@trevnorris not sure what you mean? I wasn't suggesting to pre-detect the limit. |
Although I don't exactly know what pre-detect means 😸 |
This made me believe that you intended on detecting the |
Yes, I was talking about handling it on failure: #3175 (comment) |
No no – I was talking about |
@mhart EDIT: Sorry. I've been typing For reference, here's where it's exposed: https://github.com/nodejs/node/blob/v4.1.2/src/node_buffer.cc#L979-L981 |
Oh cool! So I guess the only trickiness comes with multi-byte strings? I mean if Buffer.length > kMaxStringLength then it's not necessarily the case that string.length > kMaxStringLength – but... we could just add that to the error message anyway – in a way that doesn't necessarily imply it was the definitive cause...? "toString failed – maximum string length is 268435440" or similar? |
@mhart Sorry. It's actually a bit deeper than that. If we want to do it properly then we'll have to detect if the return value from @MylesBorins How are you approaching the problem? |
@trevnorris Ah, I assumed "empty" in |
ie: if (result === undefined) {
var kMaxStringLength = process.binding('buffer').kMaxStringLength;
if (this.length > kMaxStringLength)
throw new Error('toString failed – maximum string length is ' + kMaxStringLength);
else
throw new Error('toString failed');
} |
(that said, it does look like the |
Hah. Totally missed how With the if ((encoding === 'ucs2' || encoding === 'ucs-2' ||
encoding === 'utf16le' || encoding === 'utf-16le') &&
this.length > (kStringMaxLength / 2))
throw new Error('toString failed - buffer larger than maximum string size');
if ((encoding === 'utf8' || encoding === 'utf-8') &&
this.length > kStringMaxLength)
throw new Error('we don\'t really know this string size...');
if (this.length > kStringMaxLength)
throw new Error('assuming using a one byte encoding here'); EDIT: This is approximate and messy. Which is why simply checking if the C++ value is empty or not is the more sure way. |
For what it's worth, the error message here has been marginally improved to And, of course, it still doesn't indicate why it failed though. |
- Return `MaybeLocal`s from `StringBytes::Encode` - Add an `error` out parameter to pass JS exceptions to the callers (instead of directly throwing) - Simplify some of the string generation methods in `string_bytes.cc` by unifying the `EXTERN_APEX` logic - Reduce usage of deprecated V8 APIs. - Remove error handling logic from JS, the `buffer.*Slice()` methods now throw errors themselves. - Left TODO comments for future semver-major error message improvements. This paves the way for better error messages coming out of the StringBytes methods. Ref: nodejs#3175
- Return `MaybeLocal`s from `StringBytes::Encode` - Add an `error` out parameter to pass JS exceptions to the callers (instead of directly throwing) - Simplify some of the string generation methods in `string_bytes.cc` by unifying the `EXTERN_APEX` logic - Reduce usage of deprecated V8 APIs. - Remove error handling logic from JS, the `buffer.*Slice()` methods now throw errors themselves. - Left TODO comments for future semver-major error message improvements. This paves the way for better error messages coming out of the StringBytes methods. Ref: #3175 PR-URL: #12765 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
- Return `MaybeLocal`s from `StringBytes::Encode` - Add an `error` out parameter to pass JS exceptions to the callers (instead of directly throwing) - Simplify some of the string generation methods in `string_bytes.cc` by unifying the `EXTERN_APEX` logic - Reduce usage of deprecated V8 APIs. - Remove error handling logic from JS, the `buffer.*Slice()` methods now throw errors themselves. - Left TODO comments for future semver-major error message improvements. This paves the way for better error messages coming out of the StringBytes methods. Ref: nodejs#3175 PR-URL: nodejs#12765 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
I... don't understand why the limit is 256 MB :( |
There's an issue open on v8 too, if you'd like to star it: https://bugs.chromium.org/p/v8/issues/detail?id=6148 |
Can we rename the issue from "String length limit is small-ish" to "String length limit is small-af" |
Great news! v8 has upped the limit to ~1GB on 64-bit archs: https://chromium-review.googlesource.com/c/570047 Hopefully it comes with a nicer error message when it fails too (although that's possibly still a Node.js responsibility?) |
After 63eb267 this now returns a message |
I am running into this issue when I try to download .tar file via request and piping it to tar.x(). Does this issue imply that the maximum body size that I can download via request.get() is 1G for 64-bit machine? |
nvm.. I just had to set "encoding: null" ... which prevents the body to be passed to toString() |
I'm assuming there's some sort of memory constraint trying to convert buffers into strings?
But:
Firstly, I'm not sure that this should even be an error (are we really only limited to 256MB? That's... not very much). This seems to have been addressed in the past, but I feel like a regression might have occurred: #1374 (comment)
But that aside, can we actually detect what the error is and report on it in a more detailed way? The current
toString
check provides little insight.The text was updated successfully, but these errors were encountered: