Repository navigation
Description
Versions
Node 22.23.4, PostgreSQL 16.15, pg 8.23.1, pg-cursor 2.22.1, pg-query-stream 4.17.1. Reproduced against current master 2a5850f on Windows.
Problem
When a custom type parser throws while pg-cursor is reading rows, the exception escapes the PostgreSQL message handler. It does not reject the read promise or reach the read callback. A process can therefore terminate even though the application awaits the read inside try/catch. pg-query-stream inherits the same behavior.
The equivalent normal client.query({ text, types }) correctly rejects and leaves the client usable.
Minimal reproduction
Use the normal PGHOST/PGPORT/PGUSER/PGDATABASE configuration for a local PostgreSQL instance. Install pg and pg-cursor, then run:
const { Client } = require('pg');
const Cursor = require('pg-cursor');
async function run() {
const client = new Client();
await client.connect();
try {
const types = {
getTypeParser: () => value => {
if (value === '3') throw new Error('cannot decode value');
return Number(value);
}
};
const cursor = client.query(new Cursor(
'SELECT value FROM generate_series(1, 6) value', [], { types }
));
await cursor.read(20);
} catch (error) {
console.log('caught:', error.message);
console.log((await client.query('SELECT 42 AS answer')).rows);
} finally {
await client.end();
}
}
run().catch(console.error);Actual: uncaught Error: cannot decode value, through Result.parseRow and Cursor.handleDataRow; the inner catch is never entered and Node exits.
Expected: the read rejects with the parser error, the cursor portal is released, and the catch/finally execute. A subsequent normal query on the client should work.
Investigation
Cursor.handleDataRow() calls parseRow() without the error handling used by the core Query implementation. The correction must also respect protocol boundaries: retain the error, drain the current batch, close the portal, and report completion after ReadyForQuery. Reporting immediately without cleanup can leave the connection in an inconsistent state.
I found no matching parser-error fix in current code or targeted open/closed tracker searches. Related #3808/#3796/#3813 address timeout, close and concurrent-read behavior; #3825/#3712 address core query behavior, not this cursor parser path.
I have regression coverage for object/array rows, suspended/final batches, queued and subsequent reads, callback/promise/stream consumption, portal cleanup, error identity and a later server error. This is a reliability defect in error propagation, not a claim of a security vulnerability.
Activity