IndexedDB : dépannage
Procédure de diagnostic
Section intitulée « Procédure de diagnostic »- Ouvrir les outils de développement (
F12), onglet Console : lire le message et le nom de l’erreur. - Onglet Stockage (Firefox) ou Application (Chrome, Chromium, Edge) > IndexedDB : vérifier la base, sa version, les magasins, les index et les données.
- Identifier l’origine (schéma, domaine, port) : une autre origine a une autre base.
- Reproduire dans une fenêtre normale (la navigation privée limite IndexedDB).
console.log(await indexedDB.databases?.()); // bases de l'origine (si disponible)console.log(await navigator.storage.estimate()); // usage et quotaErreurs fréquentes
Section intitulée « Erreurs fréquentes »Erreur (erreur.name) |
Cause et solution |
|---|---|
VersionError |
Version demandée inférieure à celle de la base : augmenter la version, ou supprimer la base en développement |
NotFoundError |
Magasin ou index inexistant : schéma pas à jour (version non augmentée), faute de nom |
ConstraintError |
add d’une clé existante, ou index unique violé : put, ou traiter l’erreur |
DataError |
Clé invalide ou absente, type de clé incompatible avec l’index, plage mal formée |
DataCloneError |
Valeur non clonable (fonction, élément du DOM, objet de bibliothèque) : stocker des données simples |
InvalidStateError |
Connexion fermée, transaction terminée, ou opération hors du bon contexte (createObjectStore hors upgradeneeded) |
TransactionInactiveError |
await d’une opération étrangère à IndexedDB dans la transaction : préparer les données avant |
ReadOnlyError |
Écriture dans une transaction readonly |
QuotaExceededError |
Espace insuffisant : libérer, vérifier navigator.storage.estimate() |
AbortError |
Transaction annulée (erreur précédente, abort(), mise à jour de schéma) |
UnknownError |
Erreur interne du navigateur : base corrompue, disque plein, mode privé |
SecurityError |
Accès interdit (données de sites bloquées, iframe sandboxée, certains contextes) |
L’ouverture ne se termine jamais
Section intitulée « L’ouverture ne se termine jamais »Symptôme : indexedDB.open n’appelle ni onsuccess ni onerror.
| Cause | Solution |
|---|---|
Un autre onglet garde l’ancienne version ouverte (blocked) |
Gérer onversionchange pour fermer, informer l’utilisateur de fermer les autres onglets |
| Connexion non fermée dans l’application elle-même | Une seule connexion par onglet, la réutiliser |
upgradeneeded long (migration lourde) |
Découper la migration, afficher une attente |
| Navigateur en mode privé restrictif | Prévoir un repli (stockage en mémoire) |
requete.onblocked = () => console.warn('Fermer les autres onglets de l’application');db.onversionchange = () => { db.close(); location.reload();};Repartir de zéro en développement
Section intitulée « Repartir de zéro en développement »Pendant le développement, supprimer la base pour réinitialiser le schéma :
indexedDB.deleteDatabase('boutique');Ou dans les outils de développement : clic droit sur la base > supprimer, ou « Clear site data » (Application). Recharger la page ensuite. Après la suppression, la prochaine ouverture recrée la base avec la version courante du code.
Données qui disparaissent
Section intitulée « Données qui disparaissent »| Cause | Vérification |
|---|---|
| Navigation privée | La base est supprimée à la fermeture de la fenêtre |
| Éviction par le navigateur (espace insuffisant) | navigator.storage.persisted() ; demander persist() |
| L’utilisateur efface les données du site | Normal : prévoir une resynchronisation |
Autre origine (http / https, www, port, sous-domaine) |
Vérifier l’URL exacte |
| Autre profil de navigateur | Chaque profil a ses données |
| Nettoyage à la fermeture (réglage du navigateur) | Paramètres de confidentialité |
Performances
Section intitulée « Performances »| Symptôme | Piste |
|---|---|
| Import lent | Une transaction par élément : regrouper dans une transaction, mettre en file les écritures sans attendre chacune |
| Lecture lente | getAll() de tout le magasin : index, limite, curseur |
| Mémoire élevée | Chargement massif : curseur, pagination |
| Interface qui se fige | Traitements lourds dans le thread principal : Web Worker (IndexedDB y est disponible) |
| Requêtes lentes avec Dexie | Champ filtré non indexé (filter() parcourt tout) : déclarer l’index |
| Ouverture lente | Migration lourde ou très grosse base |
console.time('lecture');const lignes = await db.getAll('clients');console.timeEnd('lecture');Mesurer avant d’optimiser : l’onglet Performance des outils de développement montre les blocages.
Différences entre navigateurs
Section intitulée « Différences entre navigateurs »- Les quotas et les règles d’éviction diffèrent (Firefox, Chromium, Safari).
- La navigation privée se comporte différemment selon le navigateur (capacité réduite, ou indisponible dans de très anciennes versions).
- Certaines méthodes récentes (
indexedDB.databases(),getAllavec options, durabilité de transaction) ne sont pas partout disponibles : tester la présence avant usage. - Safari applique des limites plus strictes sur la conservation des données de sites peu consultés.
Tester les navigateurs ciblés ; la page de compatibilité de MDN précise la prise en charge de chaque fonction.
Tests automatiques
Section intitulée « Tests automatiques »Dans Node.js, indexedDB n’existe pas : utiliser un faux IndexedDB :
npm install -D fake-indexeddbimport 'fake-indexeddb/auto'; // définit indexedDB, IDBKeyRange… globalementimport { test } from 'node:test';import assert from 'node:assert/strict';import { ouvrirBase } from '../src/lib/db.js';
test('ouvre la base', async () => { const db = await ouvrirBase(); assert.ok(db.objectStoreNames.contains('clients'));});Pour des tests de bout en bout, un navigateur piloté (Playwright) est plus fidèle.
Dans un framework
Section intitulée « Dans un framework »| Symptôme | Piste |
|---|---|
indexedDB is not defined |
Exécution côté serveur : n’accéder à la base que dans le navigateur (voir Avec Astro, React et Next.js) |
Hydration failed après lecture de la base |
Lire dans useEffect, pas pendant le rendu |
| Données dupliquées en développement | StrictMode exécute les effets deux fois : rendre les écritures idempotentes ou nettoyer |
Ubuntu 24.04 et 26.04 : différences à connaître
Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »Aucune propre à Ubuntu. Les données de Firefox se trouvent dans le profil de l’utilisateur (avec le paquet snap, sous ~/snap/firefox/common/.mozilla/firefox/), celles de Chromium dans son propre profil : supprimer ces dossiers (navigateur fermé) réinitialise tout le stockage du navigateur, pas seulement un site.