You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Reading an empty array ('{}') throws RangeError: Invalid array length and leaves the connection unusable #129
Note: I tracked this down with the help of Claude Code (an AI coding assistant). I ran the repro below myself, and the analysis was checked against the ts-postgres and PostgreSQL sources linked here.
Version: ts-postgres 2.0.4 (the same code is still on master), Node.js v22.23.4, PostgreSQL 13
Repro
import{connect}from'ts-postgres';constclient=awaitconnect({/* ... */});console.log((awaitclient.query("SELECT '{a}'::text[] AS a")).rows);// [ [ [ 'a' ] ] ]try{awaitclient.query("SELECT '{}'::text[] AS a");}catch(e){console.log(e.message);// "Invalid array length"}console.log(client.closed);// falseawaitclient.query('SELECT 1');// rejects with "Stream not writable"
Log output:
ts-postgres: RangeError: Invalid array length
ts-postgres: Cancelled query due to an internal error
Expected:[ [ [] ] ], i.e. the column decodes to an empty array, and the connection stays usable.
Actual:
The query rejects with RangeError: Invalid array length.
The client destroys its stream (this.stream.destroy() in receive()), but client.closed stays false. A pool that checks closed to validate connections, like generic-pool with validate: c => !c.closed, keeps handing out the dead connection. Every later query on it fails with Stream not writable.
Cause
PostgreSQL represents an empty array as a zero-dimensional array (“an empty (zero-dimensional) array”, 8.15.3. Accessing Arrays), so in the binary format it arrives as ndim = 0 with no dimension headers. The decoder in readRowData computes
constdimCount=buffer.readInt32BE(offset)-1;
which is -1 for an empty array. That is not 0, so it takes the multi-dimensional branch and calls new Array(dimCount), i.e. new Array(-1).
Suggested fix: when ndim is 0, return [] before branching on dimCount. Separately, it would help if closed became true after the stream is destroyed on an internal error.
Workaround: select the column through array_to_json(col). It comes back as json, so an empty array decodes to [] and NULL to null.
Activity
空の text[] を読んだときの ts-postgres の挙動を正しく書き、上流の Issue を FIXME で参照する
malthe commentedon Oct 30, 2026
Fixed with #130.