Comment corriger CANNOT_UPDATE_CONVERTED_LEAD dans les déploiements Salesforce

Du code Apex ou API tente de mettre à jour un Lead après sa conversion, et Salesforce bloque l'écriture.

Se manifeste lors de : DML à l'exécution, le plus souvent dans un trigger, un batch job, ou un test Apex

Ce que cela signifie

CANNOT_UPDATE_CONVERTED_LEAD se déclenche lorsqu'Apex ou un appel API tente de mettre à jour un enregistrement Lead déjà converti. Une fois converti, un Lead devient en lecture seule en dehors d'un petit ensemble de champs que Salesforce autorise encore, donc toute autre mise à jour est rejetée plutôt qu'ignorée silencieusement.

C'est une erreur d'exécution plutôt que de déploiement : le trigger ou le batch job lui-même se déploie sans problème, et l'échec n'apparaît que lorsque le code s'exécute réellement sur un enregistrement converti, souvent au sein des tests Apex qu'exige un déploiement en production.

Diagnostic

Causes courantes

Le trigger ou le batch job traite les Leads sans vérifier IsConverted
L'automatisation met à jour des enregistrements Lead en masse sans exclure ceux déjà convertis.
Le script de migration met à jour les Leads sans exclure les convertis
Une migration de données touche l'objet Lead de façon large et ne limite pas la mise à jour aux seuls enregistrements non convertis.
Situation de compétition entre la requête et le DML
Un Lead est converti entre le moment où Apex l'interroge et celui où la même transaction tente de le mettre à jour.

La solution

  1. Exclure les enregistrements IsConverted = true avant de mettre à jour les Leads
    Ajoutez IsConverted = false à toute requête ou clause WHERE pilotant une mise à jour en masse de Leads.
    List<Lead> leads = [
        SELECT Id, Status FROM Lead
        WHERE IsConverted = false AND Id IN :leadIds
    ];
    update leads;
  2. Ajouter des vérifications IsConverted à la logique du trigger
    Protégez les handlers de trigger Lead pour que les enregistrements convertis soient ignorés plutôt que transmis à la logique de mise à jour.
  3. Mettre à jour l'enregistrement résultant à la place
    Une fois un Lead converti, mettez à jour le Contact, l'Account ou l'Opportunity qu'il a créé plutôt que le Lead d'origine.
En pratique

Comment Serpent évite cela

Comme Serpent exécute la suite complète de tests Apex sur chaque tâche avant qu'elle ne soit éligible au merge, un trigger qui ne filtre pas les Leads convertis échoue comme un échec de test sur la branche qui l'a introduit, pas lors d'une release en production. Voir la bibliothèque des erreurs de déploiement Salesforce.

Métadonnées et données dans un seul flux de déploiement dans Serpent

Prévention

Faire du filtrage IsConverted une protection standard des handlers de trigger
Ajoutez la vérification IsConverted à un helper de trigger partagé ou une classe de base de handler afin que chaque automatisation Lead en hérite, plutôt que de compter sur la mémoire de chaque développeur.
Couvrir un Lead converti dans la classe de test de chaque trigger Lead
Ajoutez une méthode de test qui convertit un Lead en cours de test et confirme que le trigger l'ignore proprement, afin qu'un filtre manquant échoue en CI plutôt qu'en production.
Restreindre étroitement les jobs Lead en masse
Donnez aux batch jobs et scripts de migration une clause WHERE explicite et étroite plutôt que de traiter tout l'objet Lead.
Questions fréquentes

CANNOT_UPDATE_CONVERTED_LEAD, expliqué

Puis-je mettre à jour un champ, quel qu'il soit, sur un Lead converti ?
Un petit ensemble de champs, comme ceux liés à ConvertedContactId que Salesforce gère lui-même, mais les champs métier classiques d'un Lead converti sont verrouillés.
Cela s'applique-t-il aussi aux suppressions de Lead, ou seulement aux mises à jour ?
Les suppressions sont gérées séparément et sont généralement autorisées sur les Leads convertis si les paramètres de l'org permettent la suppression de Leads en général ; cette erreur spécifique concerne le DML de type mise à jour.
Pourquoi le même trigger réussit-il dans un scratch org mais échoue-t-il dans un sandbox complet ?
Les données de test d'un scratch org contiennent rarement des Leads convertis, sauf si le test en crée un explicitement. Une copie sandbox complète de la production contient presque certainement des Leads convertis que le batch job touche désormais.

Démarrez gratuitement. Pas de carte bancaire, pas d'installation, aucun engagement.

Configuration en moins de 15 minutes. Aucun recrutement DevOps nécessaire.

Curieux de livrer plus vite avant de vous lancer ? Parlons-en

Sans engagement.