**Motivations:** - Aligner la doc API du dashboard avec les évolutions (pagination serveur, base SQLite, frais, mining, hash, UTXO, etc.) - Documenter le paramètre skipIfExists de l'API d'ancrage - Corriger les références /health pour le dashboard (utiliser /api/blockchain/info) **Root causes:** - N/A (évolution documentation) **Correctifs:** - N/A **Evolutions:** - Section API Dashboard dans api-docs.html ; endpoints utxo/count, utxo/list (pagination, category), utxo/fees, fees/update, hash/list, hash/generate, mining, transactions, anchor/example - Paramètre skipIfExists et réponses old: true/false pour POST /api/anchor/document - DASHBOARD.md : liste endpoints à jour, tests sans /health - DOMAINS_AND_PORTS.md : tests dashboard via /api/blockchain/info - features/dashboard-api-docs-update.md **Pages affectées:** - signet-dashboard/public/api-docs.html - docs/DASHBOARD.md - docs/DOMAINS_AND_PORTS.md - features/dashboard-api-docs-update.md - api-anchorage/src/bitcoin-rpc.js, bitcoin-rpc.js.backup - data/sync-utxos.log - fixKnowledge/api-anchorage-null-includes-error.md, api-anchorage-rbf-replacement-error.md
4.3 KiB
Correction: Erreur "Cannot read properties of null (reading 'includes')" dans l'API d'ancrage
Auteur : Équipe 4NK
Date : 2026-01-28
Fichier concerné : api-anchorage/src/bitcoin-rpc.js
Problème
L'API d'ancrage retournait une erreur 500 Internal Server Error avec le message :
Cannot read properties of null (reading 'includes')
Symptômes
- Erreur lors de l'appel à l'endpoint
/api/anchor/document - L'API Key est correctement validée (visible dans les logs)
- L'erreur se produit lors de l'analyse des outputs de la transaction créée
Impact
- Les requêtes d'ancrage échouent avec une erreur 500
- Aucune transaction n'est créée
- Les utilisateurs ne peuvent pas ancrer de documents
Root Cause
Dans la fonction createAnchorTransaction() du fichier bitcoin-rpc.js, à la ligne 710, le code utilisait la variable provisioningAddresses (paramètre de la fonction qui peut être null) au lieu de finalProvisioningAddresses (variable locale définie à la ligne 257 qui contient toujours un tableau valide).
Code problématique (ligne 710) :
else if (provisioningAddresses.includes(outputAddress) && Math.abs(outputAmount - provisioningAmountRounded) < 0.00000001) {
Quand provisioningAddresses est null (valeur par défaut du paramètre), l'appel à .includes() lève l'erreur "Cannot read properties of null (reading 'includes')".
Correctifs
Modification du code
Fichier : api-anchorage/src/bitcoin-rpc.js
Ligne 710 : Remplacer l'utilisation de provisioningAddresses par finalProvisioningAddresses avec une vérification de sécurité.
Avant :
else if (provisioningAddresses.includes(outputAddress) && Math.abs(outputAmount - provisioningAmountRounded) < 0.00000001) {
Après :
else if (finalProvisioningAddresses && finalProvisioningAddresses.includes(outputAddress) && Math.abs(outputAmount - provisioningAmountRounded) < 0.00000001) {
Explication
finalProvisioningAddressesest défini à la ligne 257 avec la logique :provisioningAddresses || allAddresses.slice(1, 1 + provisioningCount)- Cette variable contient toujours un tableau valide (même vide) et ne peut pas être
null - La vérification
finalProvisioningAddresses &&ajoute une sécurité supplémentaire pour éviter toute erreur future
Modifications
Fichiers Modifiés
api-anchorage/src/bitcoin-rpc.js: Correction de la ligne 710
Modalités de Déploiement
-
Redémarrer le service systemd :
sudo systemctl restart anchorage-api -
Vérifier que le service est actif :
sudo systemctl status anchorage-api -
Tester l'endpoint :
curl -X POST http://localhost:3010/api/anchor/document \ -H "Content-Type: application/json" \ -H "x-api-key: <your-api-key>" \ -d '{ "hash": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890" }'
Modalités d'Analyse
Vérification du problème
-
Consulter les logs :
sudo journalctl -u anchorage-api -n 100 --no-pager -
Rechercher l'erreur :
- Chercher "Cannot read properties of null (reading 'includes')"
- Vérifier la stack trace pour identifier la ligne exacte
-
Vérifier les paramètres :
- Vérifier que
provisioningAddressespeut êtrenulldans les appels - Vérifier que
finalProvisioningAddressesest bien défini avant utilisation
- Vérifier que
Tests de validation
-
Test avec provisioningAddresses null (cas par défaut) :
- L'appel sans paramètre
provisioningAddressesdoit fonctionner finalProvisioningAddressesdoit être un tableau généré automatiquement
- L'appel sans paramètre
-
Test avec provisioningAddresses fourni :
- L'appel avec un tableau d'adresses doit fonctionner
- Les outputs de provisioning doivent être correctement identifiés
-
Test avec provisioningCount = 0 :
- Si aucun provisioning n'est nécessaire,
finalProvisioningAddressesdoit être un tableau vide - Aucune erreur ne doit être levée
- Si aucun provisioning n'est nécessaire,
Notes
- Cette erreur se produisait uniquement lors de l'analyse des outputs de la transaction créée
- La transaction était créée avec succès, mais l'analyse des outputs échouait
- La correction garantit que
finalProvisioningAddressesest toujours un tableau valide avant l'appel à.includes()