---
name: feedback_sqlite_vacuum_into
description: Ne jamais utiliser db.backup() pour les exports — toujours VACUUM INTO ; valider avec integrity_check avant pending-restore
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 5cf6a868-7a3f-44e5-a0f8-0499f84b1afc
---

Ne jamais utiliser `db.backup()` pour créer une copie de la DB destinée à être lue comme fichier brut.

**Why:** `db.backup()` (better-sqlite3) copie les pages SQLite, y compris le header qui indique "WAL mode". Le fichier résultant est techniquement en WAL mode mais sans fichier WAL — il est incomplet et provoque `SQLITE_CORRUPT` lors de la réouverture. Incident prod constaté le 2026-06-16 : serveur en boucle de crash après restauration.

**How to apply:**

Pour tout export (route export-full, job autoExport, backup de sécurité dans la route restore) :
```js
// ✅ Correct — produit un fichier DELETE-mode propre, sans WAL
db.exec(`VACUUM INTO '${tmpDb.replace(/'/g, "''")}'`);
const dbData = fs.readFileSync(tmpDb);
```

Avant d'écrire le fichier `.pending-restore`, toujours valider :
```js
import Database from 'better-sqlite3';
const tmpValidate = path.join(os.tmpdir(), `cl-validate-${Date.now()}.db`);
let testDb;
try {
  fs.writeFileSync(tmpValidate, dbEntry.data);
  testDb = new Database(tmpValidate, { readonly: true });
  const check = testDb.pragma('integrity_check');
  if (!check || check[0]?.integrity_check !== 'ok') throw new HttpError(500, '...');
} finally {
  if (testDb) try { testDb.close(); } catch {}
  if (fs.existsSync(tmpValidate)) fs.unlinkSync(tmpValidate);
}
```

Cette validation est déjà en place dans `backend/src/routes/admin.js` (route restore).
