I have looked at that as well, and I don't think that this is fixable only from the point of psql, because the error injected creates a state where libpq's internal command queue gets out of sync regarding what the backend has sent. The only thing that could be done is inside libpq, as far as I can see, where we should try to detect that the state is not synchronized anymore and fail rather than block. So IMO, and with the error injected (which would never happen in production in practice), the best thing I can come up with is the attached for now. One thing that I could see ourselves do as an extra improvement in ExecQueryAndProcessResults() where we consume the results and check if we're still in a busy state (some PQconsumeInput+PQisBusy). I don't think that this should be a problem in practice, but this feels like just hiding the real problem on the libpq side with the inconsistent protocol state generated by the backend. I have also quickly tested an approach based on that, unfortunately this leads to some instability in the tests to due the async nature of the commands. Anyway, the v3 attached passes the regression tests, handles the pg_terminate_backend() case gracefully, handles the error case with the error injected on backend-side a but better, and can avoid some of the issues in the fourth case, but not all as we don't have access to the pipe state when reaching the results do to the backend missing up with the libpq state. Handling the 4th case more gracefully would require some libpq changes, which may not justify the cases we are dealing with here, at least to me. As a whole, I'd feel that v3 is a good improvement in itself, and it addresses your original issues and the assertions. What do you think?