Skip to content

pg-protocol can throw an uncatchable error "Cannot create a string longer than 0x1fffffe8 characters" when reading large data #2653

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

Open
laurent22 opened this issue Nov 14, 2021 · 7 comments · Fixed by supabase/node-postgres#10
Labels

Comments

@laurent22
Copy link

Using the "pg" package 8.5.1

To replicate the issue, save some large data as a blob into the database. In my case 340 MB was enough to trigger the bug. Then try to read back the data.

It will throw this uncatchable error that crashes the application:

Error: Cannot create a string longer than 0x1fffffe8 characters
    at Buffer.utf8Slice (<anonymous>)
    at Object.slice (node:buffer:593:37)
    at Buffer.toString (node:buffer:811:14)
    at BufferReader.string (/home/joplin/packages/server/node_modules/pg-protocol/src/buffer-reader.ts:35:32)
    at Parser.parseDataRowMessage (/home/joplin/packages/server/node_modules/pg-protocol/src/parser.ts:274:51)
    at Parser.handlePacket (/home/joplin/packages/server/node_modules/pg-protocol/src/parser.ts:172:21)
    at Parser.parse (/home/joplin/packages/server/node_modules/pg-protocol/src/parser.ts:101:30)
    at Socket.<anonymous> (/home/joplin/packages/server/node_modules/pg-protocol/src/index.ts:7:48)
    at Socket.emit (node:events:390:28)
    at addChunk (node:internal/streams/readable:315:12)

As a test I've tried to make it reject the promise when parser.parse(buffer, callback) throws an error in this function. At that time I can indeed catch the error, but rejecting the promise properly doesn't help for some reason and the error is still uncatchable:

export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise<void> {

Any idea what might be the issue and how to fix it?

@laurent22
Copy link
Author

I think it may be related to this TODO here, as it's try to read as UTF-8 a binary blob:

// TODO(bmc): support non-utf8 encoding?

And somewhat related is why does it try to read all fields as strings, even when it's a binary blob:

fields[i] = len === -1 ? null : this.reader.string(len)

@sehrope
Copy link
Contributor

sehrope commented Nov 14, 2021

And somewhat related is why does it try to read all fields as strings, even when it's a binary blob:

The PostgreSQL wire protocol has two modes for transferring fields: text and binary

The text mode is a string representation of each data type, such as "1234" to represent the number 1234 or "t" to represent the value true. The binary is more compact but is not documented anywhere outside of the server source.

This driver only supports reading the text mode and that class only handles text format responses:

throw new Error('Binary mode not supported yet')

Any idea what might be the issue and how to fix it?

This is still a bug though as throwing uncatchable internal errors is never acceptable. If those long values cannot be deserialized as a string then there should be a length check and a proper error message bubbled up rather than crashing.

Even when this is fixed you likely don't want to ship that much data back and forth in one piece. There's many other options including reading slices of the data as slicing into smaller bytea or using the large object API (https://www.postgresql.org/docs/current/lo-funcs.html).

@brianc
Copy link
Owner

brianc commented Nov 14, 2021 via email

@Joyjk
Copy link

Joyjk commented Jan 31, 2022

npm run serve

[email protected] serve
vue-cli-service serve

INFO Starting development server...
10% building 8/15 modules 7 active ...ytide-webapi\node_modules\webpack-dev-server\client\utils\sendMessage.js
When setting useBuiltIns: 'usage', polyfills are automatically imported when needed.
Please remove the direct import of @babel/polyfill or use useBuiltIns: 'entry' instead.
67% building 1002/1042 modules 40 active ...o\src\components\CartProdDelete.vue?vue&type=template&id=9160381e&
When setting useBuiltIns: 'usage', polyfills are automatically imported when needed.
Please remove the direct import of @babel/polyfill or use useBuiltIns: 'entry' instead.
69% building 7136/7162 modules 26 active ...odules\spdy-transport\node_modules\readable-stream\CONTRIBUTING.md n
ode:buffer:593
slice: (buf, start, end) => buf.utf8Slice(start, end),
^

Error: Cannot create a string longer than 0x1fffffe8 characters
at Object.slice (node:buffer:593:37)
at Buffer.toString (node:buffer:811:14)
at asString (H:\Laravel\Vue Nuxt Js\daytide-webapi\node_modules\webpack\lib\NormalModule.js:31:14)
at H:\Laravel\Vue Nuxt Js\daytide-webapi\node_modules\webpack\lib\NormalModule.js:347:39
at H:\Laravel\Vue Nuxt Js\daytide-webapi\node_modules\loader-runner\lib\LoaderRunner.js:373:3
at iterateNormalLoaders (H:\Laravel\Vue Nuxt Js\daytide-webapi\node_modules\loader-runner\lib\LoaderRunner.js:214:10)
at Array. (H:\Laravel\Vue Nuxt Js\daytide-webapi\node_modules\loader-runner\lib\LoaderRunner.js:205:4)
at Storage.finished (H:\Laravel\Vue Nuxt Js\daytide-webapi\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:55:16)
at H:\Laravel\Vue Nuxt Js\daytide-webapi\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:91:9
at H:\Laravel\Vue Nuxt Js\daytide-webapi\node_modules\graceful-fs\graceful-fs.js:123:16
at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) {
code: 'ERR_STRING_TOO_LONG'
}


What is the problem with my Vuejs old project? It is not running.

@laurent22
Copy link
Author

What is the problem

Is it not clear from the thread above that you, presumably, just read?

@charmander charmander added the bug label Jan 31, 2022
@xqin1
Copy link

xqin1 commented Oct 11, 2023

any updates on this bug fix? With the latest version, there is still uncatchable error with large query result. thanks

@alxndrsn
Copy link
Contributor

alxndrsn commented Sep 24, 2024

Just ran into this with v8.8.0. Hopefully there's a way to avoid converting big (> 250MB) binary fields into javascript Strings.

avallete added a commit to avallete/node-postgres that referenced this issue Mar 27, 2025
Exception occuring within the handlePacket will bubble up to pg as
uncatchables exceptions errors. Adding a try/catch and returning
an handled error allow the caller program to catch such exceptions
and decide what to do with them.

Fixes brianc#2653
avallete added a commit to avallete/node-postgres that referenced this issue Mar 27, 2025
Exception occuring within the handlePacket will bubble up to pg as
uncatchables exceptions errors. Adding a try/catch and returning
an handled error allow the caller program to catch such exceptions
and decide what to do with them.

Fixes brianc#2653
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants