database file appears corrupt / page ... is of wrong type
The two usually come together: database file appears corrupt (...), then wrong page type and page 1234 is of wrong type (expected 5, found 0).
What it means
A Firebird database is a file of fixed-size pages, each with a type in its first byte: data, index, pointer, blob, transaction inventory and so on. The engine followed a reference to page 1234 expecting one type and found another. found 0 means the page is zeroed — typical after a crash, a failing disk, a file system repair or a copy that went wrong. Another number usually means the page holds the contents of a different page.
Which data is lost depends on which page it is:
| Page type (expected) | What is lost |
|---|---|
| 5, data | the rows on that page |
| 4, pointer | for the engine, the table’s data pages listed there; the pages themselves are intact |
| 7, index | nothing: indexes are rebuilt from the data |
| 8, blob | the BLOB values stored on that page |
| 3, transaction inventory | see cannot find tip page |
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.
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.
fbrescue scan lists every page that is not what it should be, and per table how many data pages and records it can reach. For export:
- data pages that the table’s pointer pages no longer list are found by reading the whole file (each data page records its table and its place in it);
- a page found at the location of another page is read from there (Firebird 3 and later store each page’s number on the page);
- damaged index pages do not matter: export reads only the data.
Related
I/O error during "read" operation— the file ends earlycannot find tip page (165)- All errors