Visitar URL original
Keep the connection usable when a COPY API command completes without copying by Brar · Pull Request #6706 · npgsql/npgsql · GitHub
Skip to content

Keep the connection usable when a COPY API command completes without copying - #6706

Open
Brar wants to merge 1 commit into
npgsql:mainfrom
Brar:core/copy-without-copying
Open

Brar wants to merge 1 commit into
npgsql:mainfrom
Brar:core/copy-without-copying

Conversation

@Brar

@Brar Brar commented Oct 25, 2026

Copy link
Copy Markdown
Member

BeginBinaryExport, BeginBinaryImport and BeginRawBinaryCopy (and BeginTextExport and BeginTextImport, which use the raw stream) throw InvalidOperationException when the server completes the command right away, e.g. for a COPY to or from a file on the server. They left the ReadyForQuery that follows the CommandComplete unread, so the next command on the connection read it as its own response and failed with "Received backend message ReadyForQuery while expecting ParseCompleteMessage", which broke the connection. Init now reads that ReadyForQuery before it throws.

How a real server gets there

A caller passes COPY t TO '<file>', COPY t FROM '<file>' or a PROGRAM variant to one of these APIs; that needs superuser or one of the roles pg_read_server_files, pg_write_server_files and pg_execute_server_program. Npgsql only checks the COPY prefix, so the server runs the command, sends no copy response, and ends it like any other statement with CommandComplete and ReadyForQuery. This is what the user in #1673 did (BeginTextImport with COPY … FROM 'C:\temp\test.csv'), which is why the exception exists.

On PostgreSQL 18.6, all six calls (binary export and import, raw export and import, text export and import) threw the intended exception. Then SELECT 42 failed as above and the connection was broken, also after Close and a reopen from the pool, which handed out the same physical connection. The imports did import. With this PR both following commands returned their values. The released 8.0.9, 9.0.5 and 10.0.3 behave like main.

Tests

CopyTests.Copy_api_with_command_that_completes_without_copying (mock, for the three classes): on main all three cases fail with the error above; with the fix they pass.

For the reviewer

  • A core change in the COPY code (one more read in each of the three Init methods), with no API change.
  • Whether to backport this to the hotfix branches, whose releases behave like main here, is open.

Dependencies and merge order

It depends on no other PR.

Fixes #6694

…copying

BeginBinaryExport, BeginBinaryImport and BeginRawBinaryCopy (and the
text APIs built on it) throw InvalidOperationException when the server
completes the command right away, e.g. for a COPY to or from a file on
the server. They left the ReadyForQuery that follows the
CommandComplete unread, so the next command on the connection read it
as its own response and failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@roji roji left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable even if low-value - calling the BeginCopy APIs with non-STDIN/STDOUT options is a programmer bug, as these APIs are for importing/exporting data from the client application; so these aren't ever errors that are supposed to happen in a running application, which would recover and continue. Making the connection work after such programmer errors isn't really needed, but as the fix is very trivial, why not.

I wouldn't backport.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

COPY APIs leave the connection out of sync when the COPY command doesn't copy through the client

2 participants