← Retour aux Insights

RaiseError : ignorer un destinataire sans bloquer 400 000 envois

Pierre Frin Septembre 2026 7 min de lecture
un client sans conseiller, deux issues envoi de 400 000 rendu en cours RaiseError(msg) job arrêté, 0 email parti RaiseError(msg, true) un destinataire écarté, l'envoi continue journal Marketing Cloud Engagement · AMPscript · garde-fous d'envoi

Une banque de détail envoie chaque trimestre un email de prise de rendez-vous. Le nom du conseiller et son lien d'agenda sont lus dans une table de référence, à partir du code agence du client. En recette, toutes les agences de test ont un conseiller, et l'email passe la validation sans remarque.

La veille de l'envoi, un développeur ajoute une sécurité. Si le conseiller est introuvable, le code appelle RaiseError("Conseiller introuvable"). L'intention est bonne, personne ne veut d'un email qui salue un conseiller sans nom.

Le lendemain matin, l'envoi de 400 000 emails s'arrête au bout de quelques minutes, en erreur. Trois agences ouvertes le mois précédent n'avaient pas encore de conseiller dans la table de référence. Et personne ne sait combien de clients sont concernés, ni lesquels.

Le deuxième paramètre décide de tout

La fonction accepte un paramètre obligatoire et quatre facultatifs. Le deuxième est celui qui manquait dans l'incident.

RaiseError(errorMessage, boolSkipCurrentOnly, apiErrorCode, apiErrorNumber, boolPreserveDataExt)
ParamètreTypeRôle
errorMessageChaîne, obligatoireMessage associé à l'erreur
boolSkipCurrentOnlyBooléen, false par défauttrue ignore le destinataire courant et laisse l'envoi continuer, false arrête tout le job
apiErrorCodeChaîneCode d'erreur libre, utile pour les appels par API
apiErrorNumberNombreNuméro d'erreur libre
boolPreserveDataExtBooléentrue conserve les écritures en data extension faites avant l'erreur, false les annule

Un appel à un seul paramètre est donc un arrêt d'urgence, pas un filtre. La confusion est facile à faire parce que le code se lit comme une condition de sécurité alors qu'il se comporte comme une alarme incendie.

⚠️ Le piège de la recette : un garde-fou qui ne se déclenche jamais en recette n'a pas été testé. Vos jeux de données de test contiennent des clients propres, et c'est exactement ce qui empêche de voir la différence entre les deux modes.

Trois réponses à une donnée manquante

Avant d'écrire la moindre ligne, classez chaque donnée de l'email selon ce qui doit se passer si elle manque. Le classement se fait une fois, et il tient pour tous les emails de la campagne.

SituationExempleRéponse
Donnée d'agrémentPrénom absentContenu de repli avec If Empty(...)
Donnée indispensable pour ce destinataireConseiller introuvable pour son agenceIgnorer et tracer, RaiseError(msg, true, ...)
Anomalie qui touche tout l'envoiCampagne désactivée, table de référence videArrêter l'envoi, RaiseError(msg, false)
Population connue à l'avanceClients sans agence de rattachementExclure en amont par une requête SQL

Ecarter une population connue par requete

La dernière ligne compte autant que les autres. Salesforce recommande de réserver la fonction au traitement des erreurs et non à la segmentation. Si vous savez avant l'envoi qu'une population est à écarter, la retirer par une requête coûte moins cher que de l'évaluer destinataire par destinataire pendant le rendu, et le volume ciblé affiché avant l'envoi redevient juste.

Ordonner les blocs AMPscript de l'email

L'ordre des blocs traduit l'ordre des décisions. Le premier bloc de l'email contrôle ce qui touche tout le monde, paramètres de campagne et tables de référence. Le deuxième écarte les destinataires incomplets. Le troisième seulement adapte le texte.

%%[
  Var @actif
  Set @actif = Lookup("Parametres_Campagne", "Actif", "CodeCampagne", "RDV_T3")

  If Empty(@actif) Then
    RaiseError("Parametres_Campagne : ligne RDV_T3 absente", false)
  EndIf
]%%

Ce contrôle s'exécute pour chaque destinataire, mais c'est le premier qui déclenche l'arrêt. Quand la condition porte sur une date, appelez Now(true) plutôt que Now() : la fonction renvoie l'heure de début du job, la même pour tous, et le résultat ne change pas en cours d'envoi. Écrivez les messages sans accent, ils sont destinés au support et aux journaux techniques.

Tracer ceux que vous écartez

Ignorer un destinataire sans savoir lequel ne règle qu'une moitié du problème. La solution tient en une ligne écrite dans une data extension juste avant de lever l'erreur.

%%[
  Var @cle, @job, @agence, @conseiller

  Set @cle    = _subscriberkey
  Set @job    = jobid
  Set @agence = Trim(AttributeValue("CodeAgence"))

  If not Empty(@agence) Then
    Set @conseiller = Lookup("Conseillers", "NomConseiller", "CodeAgence", @agence)
  EndIf

  If Empty(@conseiller) Then

    UpsertDE("Journal_Abonnes_Ignores", 3,
             "SubscriberKey", @cle,
             "JobID", @job,
             "Motif", "CONSEILLER_ABSENT",
             "Detail", Concat("Agence : ", @agence))

    RaiseError("Conseiller introuvable", true, "CONSEILLER_ABSENT", 1001, true)
  EndIf
]%%

Trois details qui remplissent le journal

Trois détails font la différence entre un journal rempli et un journal vide. L'écriture précède l'appel, parce que le code s'arrête à l'erreur et n'exécute jamais la ligne suivante. Le cinquième paramètre vaut true, sans quoi l'écriture est annulée avec le reste. Et c'est UpsertDE qui est utilisé, pas InsertDE : l'AMPscript d'un envoi est traité par lot en dernière étape, un même destinataire peut être rendu plusieurs fois, et l'upsert évite l'échec sur une ligne déjà présente.

Le deuxième argument de UpsertDE annonce le nombre de couples de recherche qui suivent, ici trois. Si ce nombre ne correspond pas aux couples fournis, la fonction lève une exception. Relisez-le à chaque modification du bloc, c'est l'erreur la plus fréquente sur cette fonction.

Compter les destinataires ecartes en SQL

Au lendemain de l'envoi, une requête donne le décompte par agence, à transmettre à l'équipe qui gère la table des conseillers.

SELECT
    j.Detail,
    COUNT(*) AS NbClients
FROM Journal_Abonnes_Ignores AS j
WHERE j.Motif = 'CONSEILLER_ABSENT'
  AND j.DateTrace >= DATEADD(DAY, -1, GETDATE())
GROUP BY j.Detail

Posez une rétention sur ce journal dès sa création. Il ne contient que des identifiants techniques et un motif, mais il n'a pas vocation à grossir indéfiniment, et quelques mois suffisent largement à traiter les écarts constatés après un envoi.

💡 Send log ou data extension dédiée : le send log est une data extension de compte alimentée automatiquement à chaque envoi. Salesforce conseille de s'y limiter à une dizaine de champs personnalisés et à une rétention courte, de l'ordre de dix jours. Pour un journal ciblé des destinataires écartés, une table dédiée reste plus simple à interroger.

Ce que la fonction fait ailleurs

Un destinataire écarté ne disparaît pas du système, il change simplement de statut à plusieurs endroits. La documentation précise trois effets qu'on découvre souvent trop tard.

Repeter le garde-fou dans un parcours

Ce dernier point mérite qu'on s'y arrête quand un parcours enchaîne plusieurs messages sur la même donnée. Écarter un client du premier email ne le protège pas du deuxième. Soit vous répétez le contrôle dans chaque envoi, soit vous posez une condition de sortie dans le parcours lui-même.

Sur la visibilité du message d'erreur, restez prudent. Il servirait surtout aux journaux techniques et au support, et se retrouve difficilement dans l'interface. Écrivez-le sans accent et gardez le même code dans le journal et dans le troisième paramètre, le rapprochement se fera par ce code, pas par la phrase.

Si vous venez d'Adobe Campaign

Dans Adobe Campaign, les exclusions se font dans le workflow ou par des règles de typologie appliquées à l'analyse de la diffusion. Le résultat est un rapport d'exclusions lisible, où chaque destinataire écarté apparaît avec son motif. Vous ouvrez l'analyse, vous voyez les volumes, vous décidez de diffuser ou non.

Marketing Cloud ne fournit pas cette vue. Le journal construit plus haut joue le rôle du rapport d'exclusions, et c'est à vous de le construire avant le premier envoi, pas après le premier incident. Quant à l'arrêt global, il s'apparente à une règle de contrôle qui bloque la diffusion, à ceci près qu'il se déclenche pendant l'envoi et non avant. Un arrêt à six heures du matin sans notification ne sera découvert qu'à l'arrivée de l'équipe, prévoyez les alertes d'Automation Studio en conséquence.

Le réflexe à garder

Avant de publier un email qui contient un appel à cette fonction, ouvrez le code et comptez les paramètres. Un seul paramètre veut dire que le premier destinataire incomplet arrête la totalité de l'envoi. Créez ensuite une data extension de test avec une ligne par branche du code, cas nominal, donnée d'agrément absente, donnée indispensable absente, et vérifiez chaque branche en aperçu avant de programmer quoi que ce soit.

Questions fréquentes

Pourquoi RaiseError arrete-t-il la totalite de l'envoi ?

Parce que le deuxieme parametre, boolSkipCurrentOnly, vaut false par defaut. Un appel a un seul parametre est donc un arret d'urgence et non un filtre : le premier destinataire incomplet arrete tout le job. Avec true, la fonction ignore le destinataire courant et laisse l'envoi continuer.

Comment savoir quels destinataires ont ete ecartes ?

Il faut ecrire une ligne dans une data extension juste avant de lever l'erreur, car le code s'arrete a l'erreur et n'execute jamais la ligne suivante. On utilise UpsertDE plutot que InsertDE, et le cinquieme parametre de RaiseError doit valoir true, sans quoi l'ecriture est annulee avec le reste. Le lendemain de l'envoi, une requete sur ce journal donne le decompte par agence.

Les emails non envoyes a cause de RaiseError sont-ils factures ?

Non, ils ne sont pas comptes dans la consommation facturee. Ils apparaissent en revanche dans les indicateurs de suivi et de reporting, ce qui explique l'ecart constate entre le volume cible et le volume envoye.

Un destinataire ecarte sort-il du parcours ?

Non. Dans un parcours, le contact est retire d'un seul envoi : il poursuit le parcours et recevra les emails suivants, qui doivent donc avoir leurs propres garde-fous. Soit vous repetez le controle dans chaque envoi, soit vous posez une condition de sortie dans le parcours lui-meme.

Faut-il utiliser RaiseError pour exclure une population connue d'avance ?

Non. Salesforce recommande de reserver la fonction au traitement des erreurs et non a la segmentation. Si vous savez avant l'envoi qu'une population est a ecarter, la retirer par une requete coute moins cher que de l'evaluer destinataire par destinataire pendant le rendu, et le volume cible affiche avant l'envoi redevient juste.

Dans la même série
Pierre Frin
Fondateur Grokium · Consultant CRM · Certifié Adobe Campaign Classic et Salesforce Marketing Cloud Email Specialist

Vos garde-fous AMPscript tiennent-ils en production ?

Je peux relire vos blocs de personnalisation, vos exclusions et vos journaux d'envoi, et vous rendre un diagnostic écrit avec les correctifs à appliquer.

Me décrire votre contexte →