Repository navigation
Query streams break with query_timeout #1860
Description
Bug:
If a query_timeout is reached when using a submit-able query object that doesn't have a callback method on it (such as all streaming query types, and probably most user-crafted submit-ables), then the Client will throw a queryCallback is not a function error. General repro would be:
const pg = require('pg')
const QueryStream = require('pg-query-stream')
const db = new pg.Client({ ..., query_timeout: 1000 })
db.connect(err => {
if (err) throw new Error('Connection error')
const qs = new QueryStream('SELECT pg_sleep(2)')
db.query(qs)
.on('data', d => console.log('data', d))
.on('end', d => console.log('end', d))
.on('error', d => (qs.close(), console.log('error', d)))
})Analysis:
Although the node-postgres Query object has a callback method for handling bulk results, other streaming objects, such as pg-cursor and pg-query-stream, do not have such a method. Looking at the code in client.js, we see: https://github.com/brianc/node-postgres/blob/master/lib/client.js#L431-L457
If the Query object has a submit method on it, and no callback method, and if no callback is passed in as the second (values) argument to Client#query, then query.callback will be undefined. Subsequently if a readTimeout is specified (either as a query_timeout on the Query object, or as part of the database configuration), then the read timeout assumes that query.callback is defined and attempts to call it, resulting in a TypeError: queryCallback is not a function.
Fix:
Since the callback attribute appears to be an implementation detail of the node-postgres Query object, and the documentation for Client#query does not indicate that this method should be present, or that a second parameter should be passed, it's unclear whether the fix is to make callback a required attribute on all Query-like objects, or if it's to fail gracefully if such a callback does not exist.
Furthermore, it's debatable whether a query_timeout is even appropriate on non-bulk query types (timeout to results ready? timeout until entire result set has been retrieved?), and whether that timeout code should move into the typical bulk Query object itself, dodging the issue entirely.
Because that's unclear, I'm leaving it to you to decide. Happy to submit a pull-request with a fix if you can tell me where/what you think the appropriate fix is.
Activity
emilioplatzer commentedon May 5, 2019
I think that
query_timeoutis useful in other situations. For example when you have a expensive query (like a gruoup by of joins on huge tables or a function that actually calculates some complicated thing).With the
query.on('row'we can send results as they ocurr.I need the
query_timeoutbe posible in these kind of call.twooster commentedon May 6, 2019
FYI, a monkey-patch fix for those using
pg-promiseand the.streaminterface:adam-nielsen commentedon Nov 1, 2019
Is there any news on this? I am following the example at https://node-postgres.com/api/cursor and I am getting this error:
I'm not even sure why I'm getting the timeout, because I'm getting rows returned. Is it because I am taking too long to process the rows returned by the cursor?
EDIT: This does indeed seem to be the case - I am half way through processing my rows when the code aborts with the above error. Is there any way to have the timeout only active while the call to
cursor.read()is in progress, rather than leaving it active between calls?misha-erm commentedon Apr 15, 2020
vitaly-t commentedon Apr 18, 2020
pankleks commentedon Oct 27, 2020
Added default value to prevent error queryCallback is not a function
avivshafir commentedon May 9, 2022
yaverin commentedon Jul 5, 2022
casret commentedon Feb 11, 2025
Why is this still a problem after 6 years? Is there something wrong with @twooster fix that it can't go into the tree? How can we move this forward?
charmander commentedon Feb 12, 2025
@casret typically a pull request is involved in moving a change forward
carlosroberto555 commentedon Jul 23, 2025
A workaround is:
ik-southpole commentedon Sep 15, 2025
This is my workaround.
charmander commentedon Sep 16, 2025
@ik-southpole That looks like it just disables query timeouts globally?
ik-southpole commentedon Sep 16, 2025
Sorry, missed a fragment of the code :) Now updated. So basically, when I stream rows, I control already when it is enough or not. I can break the loop and close the cursor anytime. So query_timeout isn't really needed for my use case. For regular queries, timeout will still work as usual.
LuiFerPereira commentedon Jan 20, 2026
Any update about this?
I'm using
typeormwith pg-query-stream have same issuecarlosroberto555 commentedon Jan 20, 2026
See the workaround I created in the previous comments.
I used it for 6 months and it worked perfectly.