One of our threads in production hit an error and is now producing InvalidRequestError: This session is in \'prepared\' state; no further SQL can be
A surprising thing is that there's no exception handling around that self.session.commit
. And a commit can fail, for example if the connection to the DB is lost. So the commit fails, session
is not removed and next time that particular thread handles a request it still tries to use that now-invalid session.
Unfortunately, Flask-SQLAlchemy doesn't offer any clean possibility to have your own teardown function. One way would be to have the SQLALCHEMY_COMMIT_ON_TEARDOWN
set to False and then writing your own teardown function.
It should look like this:
@app.teardown_appcontext
def shutdown_session(response_or_exc):
try:
if response_or_exc is None:
sqla.session.commit()
finally:
sqla.session.remove()
return response_or_exc
Now, you will still have your failing commits, and you'll have to investigate that separately... But at least your thread should recover.