镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

pg-cursor type parser exceptions escape read error handling and crash Node #3839

Open

Description

@IbrahimHafez1

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions