postgresql error: canceling statement due to user request

This assumes that the race condition bug in the jdbc jar file for postgresql is responsible for the above error.

Workaround 1, refresh connection to database periodically

One workaround is to close the connection to the database and create a new connection to the database periodically. After every few thousand sql statements just close the connection and re-create it. Then for some reason this error is no longer thrown.

Workaround 2, turn on logging

If you turn on logging at the JDBC driver level when you are setting the driver, then in some situations the race condition problem is neutralized:

Class.forName("org.postgresql.Driver");
org.postgresql.Driver.setLogLevel(org.postgresql.Driver.DEBUG);

Workaround 3, catch the exception and re-initialize connection

You could also try catching the specific exception, re-initializing the connection and trying the query again.

Workaround 4, wait until postgresql jdbc jar comes out with a bug fix

I think the problem may be associated with the speed of my SSD hard drive. If you get this error, please post how to reproduce it consistently here, there are devs very interested in squashing this bug.


We have figured out the the cause of this issue. It's explained by buggy implementation of setQueryTimeout() in latest JDBC drivers 9.2-100x. It might not happen if you open / close connection manually, but very often happens with connection pooling in place and autocommit set to false. In this case, setQueryTimeout() should be called with non-zero value (as an example, using Spring framework @Transactional( timeout = xxx ) annotation).

It turns out, whenever SQL exception is raised during the statement execution, the cancellation timer hasn't been cancelled and stays alive (that's how it is implemented). Because of pooling, connection behind is not closed but is returned to the pool. Later on, when cancellation timer triggers, it randomly cancels the query currently associated with the connection this timer has been created with. At this moment, it's a totally different query which explains the randomness effect.

The suggested workaround is to give up on setQueryTimeout() and use PostgreSQL configuration instead (statement_timeout). It doesn't provide same level of flexibility but at least always works.