Repository navigation
🐛 [BUG] - Réconciliation SonarQube en échec 404 quand le projet à supprimer est déjà absent (deleteProject non idempotent) #2785
Description
Description
La réconciliation SonarQube échoue lorsqu'elle doit supprimer un projet SonarQube orphelin (dépôt retiré du projet côté console) qui n'existe déjà plus dans SonarQube. L'API répond 404 « Project '...' not found » et l'erreur n'est pas tolérée : toute la réconciliation du projet passe en échec (résultat de plugin KO).
Cas observé en production sur le projet testformation-demo-java-infra : la suppression du projet SonarQube testformation-demo-java-infra-77b9 (clé calculée par la console, dépôt orphelin) a reçu un 404, faisant échouer ensureProjectRepositories puis la réconciliation complète du projet.
Le cas survient lorsque le projet SonarQube visé est déjà absent au moment de la suppression : réconciliations concurrentes du même projet (rejeu de hooks pendant qu'une synchronisation est en cours, resynchronisation admin) où la première suppression réussit et la seconde reçoit un 404, ou suppression du projet SonarQube hors console entre le listing et la suppression.
Comportement attendu : une suppression « déjà effectuée » doit être idempotente (comme le tolère déjà la création avec ensure), la réconciliation ne doit pas échouer. C'est le pendant côté suppression de #2778 (échec 400 côté création).
Etapes de reproduction
- Avoir un projet portant un projet SonarQube orphelin à supprimer lors de la réconciliation (dépôt retiré du projet côté console, ou projet SonarQube supprimé hors console).
- Déclencher deux réconciliations du même projet de façon rapprochée ou concurrente (rejeu de hooks pendant une synchronisation en cours, resynchronisation admin, cron).
- Voir la seconde réconciliation échouer : « SonarQube API responded with status 404: Project '...' not found » (résultat de plugin KO pour le projet).
Captures d'écran
Logs
{"name":"SonarqubeError","message":"SonarQube API responded with status 404: Project 'testformation-demo-java-infra-77b9' not found","stack":"SonarqubeError: SonarQube API responded with status 404: Project 'testformation-demo-java-infra-77b9' not found\n at SonarqubeHttpClientService.fetch (/app/dist/src/modules/sonarqube/sonarqube-http-client.service.js:60:19)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at async SonarqubeClientService.deleteProject (/app/dist/src/modules/sonarqube/sonarqube-client.service.js:111:9)\n at async handlePromiseResult (/app/dist/src/modules/infrastructure/telemetry/telemetry.decorator.js:44:16)\n at async /app/dist/src/modules/sonarqube/sonarqube.service.js:214:17\n at async Promise.all (index 1)\n at async SonarqubeService.ensureProjectRepositories (/app/dist/src/modules/sonarqube/sonarqube.service.js:212:9)\n at async handlePromiseResult (/app/dist/src/modules/infrastructure/telemetry/telemetry.decorator.js:44:16)\n at async Promise.all (index 2)\n at async SonarqubeService.ensureProjectGroup (/app/dist/src/modules/sonarqube/sonarqube.service.js:102:9)"}Navigateurs
OS
Version de la console impactée
Observé en production (environnement dso) ; comportement présent sur main.
Définition du fini
- Une suppression de projet SonarQube déjà absent ne fait plus échouer la réconciliation (suppression idempotente)
- Des tests unitaires couvrent la suppression d'un projet déjà absent (aucun échec remonté)
- Le correctif est terminé
Références
- Sites d'appel non protégés :
apps/server-nestjs/src/modules/sonarqube/sonarqube.service.ts—ensureProjectRepositories(suppression des orphelins) etdeleteProjectGroup(suppression sur événementproject.delete) - Pend côté création : 🐛 [BUG] - Réconciliation SonarQube en échec 400 quand la clé de projet existe déjà (createProject non idempotent) #2778 ; PR de correctif : fix(sonarqube): tolerate create collisions with pre-existing entities #2779 (tolérance des collisions via
isSonarqubeAlreadyExists/ensuredanssonarqube.utils.ts) - Patron maison « déjà absent » :
VaultService.deleteMount(isVaultNotFound) dansapps/server-nestjs/src/modules/vault/vault.service.ts - Famille courses/concurrence : 🐛 [BUG] - Race condition sur les secrets Vault lors du provisionnement concurrent (symptôme :
SONAR_PASSWORD = 'not initialized') — server-nestjs #2402 (secrets Vault), Extract a shared transient-retry helper for external plugin API calls #2568 (helper de retry partagé)
Activity
shikanime commentedon Sep 28, 2026
yorha-operator commentedon Sep 28, 2026
Analyse racine
Cause :
SonarqubeClientService.deleteProjectpropage un 404 quand le projet est déjà absent, et aucun site d'appel ne l'absorbe. Deux sites concernés danssonarqube.service.ts:ensureProjectRepositories→ suppression des dépôts orphelins (stack trace production)deleteProjectGroup→ suppression sur l'événementproject.deleteDans les deux cas, un projet SonarQube déjà supprimé fait planter la réconciliation complète du projet (résultat KO).
Stack trace production (dump error format) :
Preuve de reproduction locale (client mocké, test jetable) :
handleUpsertretournestatus: KO, message « SonarQube API responded with status 404: Project '…' not found »OK, secondeKOsequenceDiagram participant A as Réconciliation A participant B as Réconciliation B participant S as SonarQube A->>S: search des projets du slug B->>S: search des projets du slug S-->>A: orphelin X listé S-->>B: orphelin X listé A->>S: POST api/projects/delete (X) S-->>A: 204 B->>S: POST api/projects/delete (X) S-->>B: 404 « Project X not found » Note over B: réconciliation KOProposition : tolérer « not found » à la suppression — ajouter
isSonarqubeNotFound(error)danssonarqube.utils.ts(pendant deisSonarqubeAlreadyExistsde #2778), et l'appliquer aux deux sites de suppression avec un log verbose « déjà absent ». Les autres erreurs continuent de se propager. Test unitaire à ajouter : orphelin déjà supprimé → réconciliation OK.Liens avec les autres issues
isSonarqubeAlreadyExists)shikanime commentedon Sep 28, 2026
Pendant GitLab du même incident : #2787 (suppression d'un dépôt orphelin échoue en 404, double
Projects.removedansdeleteProjectGroupRepo). Les deux 404 proviennent du même flux de suppression de projet.