pg_restore: error: input file appears to be a text format dump. Please use psql. — the file was written by pg_dump in its default plain format, which is an SQL script, and pg_restore reads only the archive formats. Run the file with psql -f instead; the message is the fix.

The reverse mistake has its own message: a custom-format dump (pg_dump -Fc) fed to psql makes it refuse with The input is a PostgreSQL custom-format dump. Look at the first bytes to know which one you have: an archive starts with PGDMP, a plain dump with --.

The error

$ pg_restore -U postgres -d shop_copy shop.sql
pg_restore: error: input file appears to be a text format dump. Please use psql.

The Windows client says the same, before it connects to anything:

PS> & 'C:\Program Files\PostgreSQL\18\bin\pg_restore.exe' -l shop.sql
pg_restore: error: input file appears to be a text format dump. Please use psql.

Why it happens

pg_dump writes either a plain SQL script (the default, -Fp) or an archive: custom (-Fc), directory (-Fd) or tar (-Ft). Archives carry a table of contents, which is what lets pg_restore -l list them and restore single objects. A plain script has none of that; it is just statements for psql. pg_restore reads the start of the file, finds the SQL comment header instead of an archive signature, and stops with exit code 1 without touching the database.

The file name says nothing: .sql, .dump and .backup are conventions, not formats. In the other direction, psql 18 recognised the custom-format file both with -f and on standard input, printed its two-line hint and also exited with code 1.

The fix

$ head -c 5 shop.dump
PGDMP
$ head -n 3 shop.sql
--
-- PostgreSQL database dump
--

On Windows, Format-Hex shows the same bytes; the first line of its output, after the path header, was:

00000000   50 47 44 4D 50 01 10 00 04 08 01 01 00 2D 00 00  PGDMP........-..

A plain dump goes to psql, into an existing empty database:

$ createdb -U postgres shop_copy2
$ psql -U postgres -d shop_copy2 -q -f shop.sql
 set_config
------------

(1 row)

The one-row result is the dump's own set_config call, not an error; the customers table arrived with its row. A custom-format dump goes to pg_restore:

$ pg_restore -U postgres -d shop_copy shop.dump
$ psql -U postgres -d shop_copy -c '\dt'
              List of tables
 Schema |     Name      | Type  |  Owner
--------+---------------+-------+----------
 public | customers     | table | postgres
 public | orders        | table | postgres
 public | orders_import | table | postgres
(3 rows)

If you control the backup, prefer -Fc: the same file can then be listed with pg_restore -l before you restore anything, as the Windows client did here.

How it was reproduced

A postgres:18 container (PostgreSQL 18.4) on Docker 29.9.2 under Windows 11, with pg_dump, pg_restore and psql 18.4 inside it. The database shop held three small tables and was dumped twice: pg_dump -U postgres -d shop -f shop.sql and pg_dump -U postgres -d shop -Fc -f shop.dump. Each file was then handed to the wrong tool and the right one, restoring into empty databases. The Windows checks used pg_restore.exe 18.3 from a PostgreSQL 18 install on files copied out with docker cp. The names fix7-pg, shop, shop_copy and shop_copy2 are this test's own, and the container was removed afterwards.

Frequently asked

How do I restore a .sql file made by pg_dump?
A .sql file from pg_dump is a plain SQL script, so run it with psql into an existing empty database: createdb -U postgres newdb, then psql -U postgres -d newdb -f file.sql. pg_restore cannot read it and says so.
How do I tell whether a PostgreSQL dump is plain SQL or custom format?
Look at the first bytes. A custom-format archive starts with PGDMP; a plain dump starts with a comment line such as -- PostgreSQL database dump. On Linux use head -c 5, on Windows Format-Hex. pg_restore -l also lists the contents of an archive and refuses a plain file.
Why does psql say The input is a PostgreSQL custom-format dump?
The file was made with pg_dump -Fc, which writes an archive rather than SQL. Restore it with pg_restore -d targetdb file instead of psql.

More decoded errors in the Fixes category. For choosing a format and a routine in the first place, see PostgreSQL backup and restore for SQL Server DBAs.