# 22P04 — bad_copy_file_format

> Source-backed reference for PostgreSQL SQLSTATE 22P04.
---

# 22P04

## At a glance {#at-a-glance}
`22P04` is the COPY file-format boundary. The fixed parser uses it for binary signatures and headers, text or CSV framing, header/row field counts, and malformed binary field lengths. It is a structural COPY error, not a generic synonym for a value that failed type conversion.

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| Field | Value |
| --- | --- |
| SQLSTATE | `22P04` |
| Condition | `bad_copy_file_format` |
| Status | `active` |
| Known present by | `7.4` |
| Locked snapshots | `9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| Macros | `ERRCODE_BAD_COPY_FILE_FORMAT` |
| Aliases | `—` |

<!-- source facts: data/errcodes/22P04.json -->
<!-- END SQLSTATE FACTS -->

## Meaning {#meaning}
Binary input validates the `PGCOPY` signature, flags, extension length, row field count, field length, and end marker. Representative primaries include `COPY file signature not recognized`, `invalid COPY file header (missing flags)`, `invalid COPY file header (wrong length)`, `row field count is %d, expected %d`, `invalid field size`, and `unexpected EOF in COPY data`.

Text and CSV input has separate framing guards. Header matching can report `wrong number of fields in header line: got %d, expected %d` or a column-name mismatch; ordinary rows can report `extra data after last expected column` or `missing data for column "%s"`. CSV quoting and line endings can report `unterminated CSV quoted field`, `unquoted carriage return found in data`, or `unquoted newline found in data`, while text mode uses the corresponding `literal ... found in data` messages and hints. A valid frame whose value cannot be converted belongs to the type-input boundary, commonly `22P02`; a binary type receiver that leaves bytes unconsumed can be `22P03`.

## Messages {#messages}
Representative fixed `ERROR` primaries include:

- Binary headers/fields: `COPY file signature not recognized`; `invalid COPY file header (missing flags)`; `unrecognized critical flags in COPY file header`; `invalid COPY file header (missing length)`; `invalid COPY file header (wrong length)`; `invalid field size`; `unexpected EOF in COPY data`.
- Header and rows: `wrong number of fields in header line: got %d, expected %d`; `column name mismatch in header line field %d: got "%s", expected "%s"`; `extra data after last expected column`; `missing data for column "%s"`; `row field count is %d, expected %d`.
- CSV and line framing: `unterminated CSV quoted field`; `literal carriage return found in data`; `unquoted carriage return found in data`; `literal newline found in data`; `unquoted newline found in data`; `end-of-copy marker is not alone on its line`. The carriage-return/newline variants carry the source hints to use `\r`, `\n`, or a quoted CSV field.

## Diagnosis {#diagnosis}
Determine whether the source is text, CSV, binary COPY, or frontend COPY-in. Preserve the exact primary because it identifies the parser stage. Check binary signature/flags/length, header and target-column order, row field count, CSV quote/escape and newline rules, and whether the text COPY end-of-data marker is alone on its line. Only after framing is valid should you investigate the target type's input conversion.

`ON_ERROR IGNORE` is narrower than a general malformed-row switch. The fixed text/CSV path wraps safe type-input conversion and can emit a notice while skipping a data-type-incompatible row; header, field-count, line-framing, CSV-quote, and binary-structure errors are raised as `ERROR` and are not all skippable through that option.

## Response {#response}
Regenerate the stream in the declared text/CSV/binary format with the exact target column order and correct headers, lengths, quoting, and row framing. In frontend COPY-in, finish the COPY sub-protocol at its current boundary, using `CopyFail` when appropriate. If the COPY was issued through the extended protocol and the backend sends `ErrorResponse`, send `Sync` and wait for `ReadyForQuery`; if it was issued in a simple `Query`, the remaining query message is discarded and `ReadyForQuery` follows; no client `Sync` is required, so consume that `ReadyForQuery` before sending the next query. Do not send ordinary SQL in the middle of COPY-in. An `ERROR` inside an explicit transaction requires `ROLLBACK` or `ROLLBACK TO SAVEPOINT` after the protocol boundary; `ReadyForQuery` reports status but does not replace that transaction recovery. `ON_ERROR IGNORE` may be suitable for the documented safe type-input failures, but it does not repair a bad header or malformed CSV/binary framing. A normal COPY ERROR does not by itself require resetting the connection.

## Versions {#versions}
The locked catalogue records this condition from PostgreSQL `7.4`. The cited parser and its `ON_ERROR` boundary are from PostgreSQL 18.6 `REL_18_6`; no natural COPY-file runtime was executed.

## Related {#related}
[`22P02`](../22p02/), [`22P03`](../22p03/), [`2200B`](../2200b/)

## Sources {#sources}
[`src/backend/commands/copyfromparse.c#L190-L228`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/copyfromparse.c#L190)

[`src/backend/commands/copyfromparse.c#L779-L827`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/copyfromparse.c#L779)

[`src/backend/commands/copyfromparse.c#L937-L977`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/copyfromparse.c#L937)

[`src/backend/commands/copyfromparse.c#L1026-L1073`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/copyfromparse.c#L1026)

[`src/backend/commands/copyfromparse.c#L1084-L1130`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/copyfromparse.c#L1084)

[`src/backend/commands/copyfromparse.c#L1388-L1432`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/copyfromparse.c#L1388)

[`src/backend/commands/copyfromparse.c#L1818-L1922`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/copyfromparse.c#L1818)

[`src/backend/tcop/postgres.c#L416-L445`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/postgres.c#L416)

[`doc/src/sgml/protocol.sgml#L1287-L1318`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/protocol.sgml#L1287-L1318)

The structured [evidence record](../data/evidence/22p04.json) records representative exact primaries/hints and the structural `ON_ERROR` limit.
