fbrescue

I/O error during "read" operation for file

On Windows the operation is called "ReadFile"; the next line is usually Error while trying to read from file, sometimes with Reached the end of the file or an operating system error.

What it means

The engine asked the operating system for a page and did not get it. Either the page is beyond the end of the file — the file is shorter than the database thinks: a copy that stopped half way, a full disk, a download cut short — or the disk could not read it.

If the disk is failing, stop using it: every read can make it worse. Copy the file to another disk first, with a tool that skips unreadable sectors if needed (ddrescue on Linux), and work on the copy.

If the file is truncated, the pages past the end are gone, and so are the rows on them. Everything before the cut can be saved.

First: make a copy, and work only on the copy

Stop the Firebird server, or at least make sure nothing is connected to the database. Then copy the file, together with any .delta file next to it (an nbackup lock) and the secondary files of a multi-file database. A copy taken while the server writes to the file is inconsistent, and every repair attempt changes the file it runs on. If the disk itself is failing, copy the file to another disk before anything else.

Then: try Firebird’s own tools

These come with every Firebird installation and often get a database back as a whole: indexes, triggers, users and all. On the copy:

gfix -v -full -n copy.fdb            # validate, report only
gfix -mend -full -ignore copy.fdb    # let gbak skip damaged records
gbak -b -v -ig -g copy.fdb copy.fbk  # back up: no checksums, no GC
gbak -c -v copy.fbk restored.fdb     # restore into a new database

Add -user SYSDBA -password ... as your server needs. If gbak -b completes, the restored database is the result: check the row counts of the important tables. gfix -mend throws away the records it cannot read, so compare with the original before you rely on the restored copy.

gbak often stops at the first page it cannot read, even when most of the database is intact.

If gbak still fails: get the data out with fbrescue

fbrescue reads the database file directly, without the Firebird engine, and exports every row it can read. It does not stop at the first damaged record or page, and it never writes to the file. Download the single binary for your system from Releases (Windows, Linux, macOS; nothing to install).

fbrescue scan copy.fdb                               # what is damaged, by table
fbrescue export copy.fdb --out rescued --format sql  # schema.sql + INSERTs per table

--format csv and --format jsonl are there too. Rows that could not be read are listed in rescued/_errors.jsonl with the page and the reason, and the exit status is 2 when anything was left out. To load the result into a new database:

isql -ch UTF8 -i rescued/schema.sql new.fdb
isql -ch UTF8 -i rescued/CUSTOMERS.sql new.fdb  # and so on for each table

If you would like help, open an issue and attach the output of fbrescue report copy.fdb: it describes the damage without any of your data, and with table and column names replaced by numbers.

For a truncated file, fbrescue scan reports the pages that are referenced but no longer in the file, and which tables they belong to. Export reads every page that is still there and lists the rows and values it could not read; blobs whose pages are gone are written as NULL, the rest of their row is kept.