This issue was previously reported in the mailing list in January 2019 and there is an open PR #1387 by @sehrope with a proposed solution. However his solution introduces breaking changes in the API. Although I cannot disagree that public APIs of PGCopyOutputStream/PGCopyInputStream require overhaul (every CopyIn method implementation in PGCopyOutputStream throws an NPE after the stream is closed), this can be done later, together with possibly other incompatible changes in the driver.
Right now I propose checking if the copy operation is active before ending it for the second time. Similar approach is done in PGCopyInputStream. I can write a PR with the change if needed, provided it gets merged and released faster.
So basically my fix is ready. In theory we could fix all CopyIn implementation methods to return something meaningful after copy has ended (getFieldCount(), getFieldFormat(), etc. - they are known at the time of stream construction once the delegate CopyIn is created), or at least throw something other than a NullPointerException (other methods that require writing to backend), but I'd make that a separate effort.