"Database disk image is malformed"

Das ist Fehlercode 11, SQLITE_CORRUPT: Beim Durchlaufen eines B-Trees stieß SQLite auf eine Seite oder einen Zeiger, der keinen Sinn mehr ergibt, und weigert sich deshalb, der Datei zu vertrauen. Die Zeilen selbst liegen fast immer noch auf der Festplatte — kaputt ist die Karte, die zu ihnen führt — und um sie zu erreichen, muss deine Datenbank nirgendwohin gesendet werden.

Deine Datei verlässt nie dein Gerät — die Reparatur läuft in deinem Browser. 0 Bytes hochgeladen.

Your data is the big block — usually intact. What breaks is the small index. Repair rebuilds it.

Drop a file here or browseTap to choose a file

ZIP · Office · PDF · video · JPG · PNG · RAR/7z · SQLite — repaired right here in your browser. Nothing is uploaded

0 bytes uploadedFree: 3 repairs/day — up to 500 MB video, 100 MB docs & archives, 50 MB photos. Free download. Single repair €5.90. No account required.

Jetzt reparieren

  1. Datei ablegen
  2. Reparatur läuft lokal
  3. Ergebnis herunterladen

Wenn SQLite — oder irgendetwas, das darauf aufbaut: der Verlauf eines Browsers, das Backup eines Smartphones, die lokale Datenbank einer Messaging-App, die Einstellungen einer Desktop-Anwendung — "database disk image is malformed" meldet, ist es auf SQLITE_CORRUPT (Ergebniscode 11) gestoßen. Es durchlief gerade den B-Tree, der deine Tabellen indiziert, und landete auf einer Seite, deren Typ-Byte, Zellzeiger oder Datensatzkopf dem Format widersprechen, also hält es an, statt Datenmüll zurückzugeben. Lege die .db-, .sqlite- oder .sqlite3-Datei oben ab und das Werkzeug liest sie Seite für Seite in deinem Browser, folgt der B-Tree-Struktur, die überlebt hat, durchkämmt den Rest mit einem zeigerfreien Scan und schreibt jede dekodierbare Zeile in eine brandneue, öffenbare Datenbank — ohne dass die Datei jemals dein Gerät verlässt.

Was "malformed" auf Seitenebene bedeutet

Eine SQLite-Datenbank ist eine einzige Datei, zerlegt in Seiten fester Größe — eine Zweierpotenz zwischen 512 und 65536 Bytes, gespeichert als 16-Bit-Wert am Offset 16 des Headers (der auf der Festplatte stehende Wert 1 ist die Art und Weise, wie die Spezifikation 65536 darstellt). Jede Datei beginnt mit der 16 Byte langen magischen Zeichenkette SQLite format 3\0, gefolgt von einem 100 Byte langen Header, der die Seitengröße festhält, die Textkodierung am Offset 56 (1 = UTF-8, 2 = UTF-16le, 3 = UTF-16be), die im Header angegebene Seitenzahl am Offset 28 und die Freiliste (freelist). Wird die Seitengröße falsch gelesen, landet jede Seite nach der ersten am falschen Offset — und das ist eine der Arten, wie eine Datei "malformed" wird, ohne dass eine einzige Zeile angetastet wird.

Im Inneren leben die Daten in B-Trees. Jede Seite beginnt mit einem Typ-Byte: 0x0d für ein Tabellenblatt (das die eigentlichen Zeilen enthält), 0x05 für eine innere Tabellenseite (die nur Zeiger auf Kindseiten enthält) und 0x0a/0x02 für die Index-Entsprechungen. Seite 1 ist besonders — ihr B-Tree-Header steht nach dem 100 Byte langen Datenbank-Header — und sie ist die Wurzel von sqlite_master, der Schema-Tabelle, deren Zeilen (type, name, tbl_name, rootpage, sql) lauten. Um eine deiner Tabellen zu lesen, schlägt SQLite dort ihre rootpage nach, steigt dann über die inneren Seiten bis zu den Blättern hinab und liest aus jeder Zelle die Nutzlastlänge (varint), die rowid (varint) und den Datensatzrumpf.

Da eine Abfrage diesen Baum durchläuft, vergiftet ein einziger kaputter Verweis alles darunter. Eine auf Null gesetzte innere Seite, ein Zellzeiger, der über das Ende der Seite hinaus zeigt, ein Zeiger auf das rechte Ende, der eine Schleife bildet, oder ein Datensatzkopf, dessen Serientypen nicht aufgehen — jedes davon lässt SQLite "database disk image is malformed" auslösen, sobald es auf den Schaden tritt. Die Zeilen auf den gesunden Blattseiten sind unversehrt; SQLite kann sie nur über einen kaputten Index nicht mehr erreichen. PRAGMA integrity_check meldet dieselbe Fehlerklasse.

Wie ein roher Seitendurchlauf deine Zeilen rettet

Die Lösung ahmt nach, was der eigene .recover-Befehl der SQLite-Shell tut, läuft aber vollständig im Browser. Zuerst liest das Werkzeug sqlite_master von Seite 1, um den Namen jeder Tabelle, ihre Spalten (aus dem SQL ihres CREATE TABLE geparst) und ihre rootpage zu erfahren, und durchläuft dann jeden B-Tree von dieser Wurzel aus — der schnelle, exakte Weg, wenn die Zeiger intakt sind. Trifft ein Durchlauf auf eine fehlende oder ungültige Seite, stuft er auf "unvollständig" herab, statt abzubrechen, und behält jede Zeile, die er bis zum Bruch gesammelt hat.

Dann kommt der Teil, der ein bloßes erneutes Öffnen übertrifft: ein zeigerfreier Durchgang. Der Scanner ignoriert alle Zeiger und behandelt jede Tabellenblattseite (Typ 0x0d) der Datei als einen Sack voller Datensätze und dekodiert jede Zelle direkt aus ihren Bytes — die Header-Länge (varint), das Serientyp-Array und dann jeden Wert (Serientyp 0 ist NULL, 8/9 sind die Literale 0 und 1, 7 ist ein float64, und gerade/ungerade Codes über 12 sind BLOB/TEXT). Die Overflow-Ketten großer Werte werden von Seite zu Seite verfolgt. Genau so überleben Zeilen eine auf Null gesetzte innere Seite, eine Seite in der Freiliste oder eine gelöschte Tabelle: Das Blatt enthält die Daten weiterhin, auch wenn nichts mehr darauf zeigt. Zeilen, deren Spaltenzahl eindeutig zu einer bekannten Tabelle passt, werden wieder in sie eingefügt; die wirklich nicht zuordenbaren werden in eine Tabelle lost_and_found mit den Spalten pgno, cellidx, nfield, rowid und c0…cN geschrieben, sodass nichts Dekodierbares verworfen wird.

Zuletzt baut das Werkzeug eine neue Datenbank mit sqlite3.wasm (vom selben Origin unter /engines/sqlite/ geladen) und gibt für jede Tabelle ein nachsichtiges CREATE TABLE aus — die ursprünglichen Spaltennamen und jeder INTEGER PRIMARY KEY bleiben erhalten, damit der rowid-Alias erhalten bleibt, aber ohne NOT NULL/UNIQUE/CHECK/Fremdschlüssel-Einschränkungen, die eine wiederbelebte Zeile ablehnen würden — und führt dann für jede wiederhergestellte Zeile ein INSERT OR IGNORE aus und exportiert das Ergebnis als saubere .db. Wird eine benachbarte -wal-Datei (Write-Ahead-Log) bereitgestellt, werden zunächst ihre bestätigten Frames überlagert, sodass die Wiederherstellung die letzte bestätigte Transaktion widerspiegelt.

Wo die Daten wirklich enden — und warum nichts hochgeladen wird

Die Wiederherstellung erreicht, was vorhanden ist; sie kann nicht erfinden, was die Festplatte nicht mehr enthält. Wurde die Datei abgeschnitten (truncated) — eine Kopie oder Synchronisierung, die zu früh anhielt und eine Größe hinterließ, die kein exaktes Vielfaches der Seitengröße ist — so ist jede Seite nach dem Schnitt physisch verschwunden, und du erhältst die Zeilen, die davor vollständig geschrieben wurden. Zellen, die auf intakten Seiten liegen, deren Datensatzkopf aber in sich widersprüchlich ist (der klassische Bit-Rot), werden verworfen und gezählt, statt erraten zu werden. Eine verschlüsselte Datenbank (SQLCipher oder die SEE-Erweiterung) hat keine magische Zeichenkette im Klartext — ihre erste Seite ist Chiffretext — also gibt es ohne den Schlüssel nichts zu durchlaufen, und eine Wiederherstellung wird nicht versucht.

Zwei Ehrlichkeitshinweise, auf denen SQLite selbst besteht. Gelöschte Zeilen können wieder auftauchen: Der zeigerfreie Scan liest Seiten aus der Freiliste und noch nicht kompaktierte (vacuum) Seiten, sodass Datensätze, die du für verschwunden hieltest, im Ergebnis wieder auftauchen können. Und die wiederhergestellten Werte spiegeln die Speicherklassen auf der Festplatte wider, nicht die deklarierten Spaltenaffinitäten — der scheinbare Typ einer Spalte kann sich verschieben. Die eigene Anleitung von SQLite ist unmissverständlich: Daten, die aus einer beschädigten Datenbank gezogen werden, sind immer verdächtig. Prüfe sie gegen eine bekannt gute Quelle, bevor du dich darauf verlässt.

All das läuft im Tab deines Browsers — der Scanner ist abhängigkeitsfreies TypeScript und der Schreiber ist WASM, es gibt also keinen Umweg über einen Server. Das zählt, wenn die Datenbank ein Passwort-Tresor, ein Chatverlauf, Gesundheitsdaten oder der private Speicher einer App ist: Du kannst den Netzwerk-Tab öffnen und bestätigen, dass 0 Bytes der Datei jemals dein Gerät verlassen.

Was sich reparieren lässt und was nicht

Kann repariert werden

  • Datenbanken, die SQLITE_CORRUPT / "database disk image is malformed" wegen einer beschädigten B-Tree-Seite oder eines beschädigten Zeigers auslösen
  • Zeilen auf gesunden Tabellenblattseiten, die eine kaputte innere Seite oder eine defekte rootpage unerreichbar gemacht hat
  • Zeilen auf auf Null gesetzten inneren Seiten, Seiten in der Freiliste oder gelöschten Tabellen, wiederhergestellt durch den zeigerfreien Blattscan
  • Große Werte, die auf Ketten von Overflow-Seiten übergelaufen sind, während des Durchlaufs wieder zusammengesetzt
  • Nicht per Checkpoint gesicherte Änderungen in einer benachbarten -wal-Datei, vor dem Scannen überlagert

Kann nicht repariert werden

  • Zeilen nach dem Schnitt in einer abgeschnittenen Datei — diese Seiten sind physisch verschwunden
  • Zellen, deren Datensatzkopf zu stark beschädigt ist, um dekodiert zu werden (Bit-Rot) — sie werden verworfen, nicht erraten
  • Verschlüsselte SQLCipher-/SEE-Datenbanken ohne den Schlüssel (die Seiten sind Chiffretext)
  • Die ursprünglichen UNIQUE-/CHECK-/Fremdschlüssel-Garantien — die Wiederherstellung lockert die Einschränkungen, damit wiederbelebte Zeilen nicht abgelehnt werden
  • Eine Datei mit 0 Bytes oder ohne SQLite-Magie und ohne dekodierbare Blattseiten

Wenn eine Reparatur fehlschlägt, sagen wir dir warum (fehlende Daten gegenüber beschädigter Struktur), und für eine fehlgeschlagene Reparatur wird dir nie etwas berechnet.

Häufige Fragen

"Database disk image is malformed" — bedeutet das, dass meine Daten verloren sind?

Meistens nicht. Es bedeutet, dass SQLite dem B-Tree bis zu einer Seite oder einem Zeiger folgte, der das Format verletzt, und anhielt — Fehlercode 11, SQLITE_CORRUPT. Die Zeilen auf den gesunden Blattseiten liegen weiterhin auf der Festplatte; sie sind nur über den kaputten Index nicht erreichbar. Die Blattseiten direkt zu lesen und eine neue Datenbank neu aufzubauen stellt die meisten davon wieder her.

Worin unterscheidet sich das vom bloßen erneuten Öffnen der Datei oder dem Ausführen von PRAGMA integrity_check?

Erneutes Öffnen scheitert auf dieselbe Weise, und integrity_check meldet den Schaden nur. Die Wiederherstellung durchläuft stattdessen den B-Tree, wo sie kann, und macht vor allem einen zeigerfreien Scan jeder Tabellenblattseite — so rettet sie Zeilen auf Seiten, auf die nichts mehr zeigt, was ein normales Öffnen niemals erreichen kann.

Was ist die Tabelle lost_and_found in der wiederhergestellten Datenbank?

Dort werden Datensätze aufbewahrt, statt verworfen, die keiner bekannten Tabelle zugeordnet werden konnten. Jeder wird mit seiner Quell-Seitennummer (pgno), dem Zellindex, der Feldanzahl und der rowid gespeichert, dazu seine rohen Spaltenwerte als c0, c1 und so weiter — damit du sie prüfen und von Hand neu zuordnen kannst.

Warum sind nach der Wiederherstellung gelöschte Zeilen aufgetaucht?

Der zeigerfreie Scan liest Seiten aus der Freiliste und noch nicht kompaktierte (vacuum) Seiten, wo SQLite alte Datensätze belässt, bis der Platz wiederverwendet wird. Die Wiederherstellung bevorzugt Vollständigkeit, sodass zuvor gelöschte Zeilen wieder auftauchen können. Behandle alle wiederhergestellten Daten als verdächtig und prüfe sie gegen eine bekannt gute Quelle.

Wird meine Datenbank zur Wiederherstellung hochgeladen?

Nein. Die Datei wird von deiner Festplatte gelesen und im Tab deines Browsers neu aufgebaut; der Seitenscanner ist reines TypeScript und der Schreiber ist sqlite3.wasm, ausgeliefert vom selben Origin. Du kannst den Netzwerk-Tab beobachten und bestätigen, dass 0 Bytes hinausgehen — was bei Chatverläufen, Passwort-Tresoren, Backups und Gesundheitsdaten zählt.

Verwandt: Eine SQLite-Datenbank reparieren · Eine Excel-Arbeitsmappe reparieren · "The file is damaged and could not be repaired" · Prüfen, dass nichts hochgeladen wird