Votre pipeline s’exécute désormais sans surveillance, sur un serveur, déclenché par un ordonnanceur. Un matin, le rapport est vide et le log affiche une ligne peu aimable : Unable to convert value to date. Trois millions d’enregistrements corrects n’ont pas été chargés à cause d’un seul champ mal formé dans un fichier de 400 Mo, et vous ne savez ni lequel, ni combien il en existe d’autres.
C’est le comportement par défaut d’un pipeline : la première erreur remonte, le traitement s’arrête. Choix prudent, mais pas toujours le bon. Apache Hop propose un mécanisme dédié, l’error handling, qui détourne les lignes fautives vers un second flux au lieu d’interrompre le traitement. Cet article montre comment le mettre en place, comment le borner par des seuils, et comment décider de ce qui doit malgré tout provoquer un arrêt.
Prérequis
- Apache Hop 2.19.0 (version stable publiée le 17 août 2026) ou une version récente
- Java 21, requis par la page de téléchargement officielle
- Un pipeline fonctionnel qui lit une source et alimente une cible
1. Deux niveaux d’erreur à ne pas confondre
Dans un pipeline, les données circulent d’un transform à l’autre. Une erreur y concerne une ligne : conversion impossible, contrainte violée, valeur hors bornes. C’est le terrain de l’error handling, et le hop qui transporte ces lignes rejetées s’affiche en rouge dans l’éditeur.
Dans un workflow, aucune donnée ne circule. La documentation est explicite : les actions s’exécutent séquentiellement et ne s’échangent rien par leurs connexions, chacune produisant un statut de succès ou d’échec. Les hops y portent trois couleurs : vert en cas de succès, orange en cas d’échec, noir pour un enchaînement inconditionnel qui ignore le statut de sortie. Une erreur y concerne un traitement entier.
La règle pratique : le pipeline gère les lignes qui posent problème, le workflow gère les traitements qui ont échoué.
2. Activer l’error handling sur un transform
Cliquez sur l’icône du transform pour ouvrir son menu contextuel, puis choisissez l’icône Error handling. La boîte de dialogue demande une case enable the error handling et un target transform, celui qui recevra les lignes rejetées. Viennent ensuite quatre champs facultatifs qui, s’ils sont renseignés, ajoutent chacun une colonne au flux d’erreur. Sans eux, vous récupérez des lignes rejetées sans savoir pourquoi.
| Champ | Contenu ajouté au flux d’erreur |
|---|---|
nr of errors fieldname |
Le nombre d’erreurs relevées sur la ligne |
error description fieldname |
Le message d’erreur en clair |
error fields fieldname |
Le ou les champs à l’origine du rejet |
error codes fieldname |
Le code d’erreur |
Renseignez les quatre : le coût est nul, et le jour où vous devez expliquer un écart de volumétrie, vous disposez d’un rapport exploitable plutôt que d’un fichier de lignes orphelines. Une réserve : la documentation ne publie pas la liste des transforms qui supportent ce mécanisme, mais la vérification est immédiate — si l’icône Error handling n’apparaît pas dans le menu contextuel, le transform ne le gère pas.
Le target transform peut être n’importe quel transform. Un Text File Output écrivant un fichier de rejets daté à côté de la source couvre la plupart des cas ; un Table Output convient mieux si vous suivez les taux d’erreur dans le temps. Dans les deux cas, écrivez les colonnes de diagnostic et les données d’origine : une ligne rejetée sans son contenu ne se corrige pas.
3. Poser des seuils plutôt que tout accepter
Détourner les erreurs ne suffit pas : sans limite, un fichier décalé d’une colonne produira trois millions de rejets et un chargement vide, sans qu’aucune alerte ne se déclenche. La même boîte de dialogue propose trois garde-fous.
max nr errors allowed— le nombre d’erreurs au-delà duquel le transform est en échecmax % errors allowed (empty = 100%)— la même tolérance exprimée en pourcentage ; laissé vide, elle vaut 100 %, autrement dit aucune limitemin nr of rows to read before doing % evaluation— le nombre de lignes à lire avant d’évaluer ce pourcentage
Ce troisième champ est celui qu’on oublie. Sans lui, le pourcentage se calcule dès les premières lignes : deux rejets sur trois enregistrements déclenchent un échec à 66 %, alors que le reste du fichier est sain. Un réglage raisonnable en production : 1 à 2 % d’erreurs tolérées, évalués après 5 000 lignes. Vous absorbez le bruit habituel et vous détectez la rupture de format.
4. Valider en amont plutôt que rattraper en aval
L’error handling réagit à des erreurs techniques : une conversion qui échoue, une contrainte de base rejetée. Il ne dit rien des règles métier — un code postal à trois chiffres ou un statut hors nomenclature passeront sans encombre jusque dans votre table cible.
C’est le rôle du transform Data Validator, qui applique des règles déclaratives par champ : Verify data type, Null allows?, Min string length et Max string length, Minimum value et Maximum value, Regular expression expected to match, ou une liste d’Allowed values. Chaque règle porte son Error code et son Error description, qui se retrouvent dans le flux de rejet.
Deux options générales méritent attention. Report all errors, not only the first poursuit la validation au-delà du premier échec — sans elle, vous corrigerez les anomalies une par une, à raison d’un chargement par correction. Output one row, concatenate errors with a separator regroupe alors tous les motifs sur une seule ligne. Le Data Validator supportant lui-même l’error handling, branchez-le sur le même flux de rejets : toutes les anomalies convergent vers un fichier unique.
5. Le piège du chargement en base
Un cas revient systématiquement : vous cherchez à isoler les doublons de clé primaire sur un Table Output, et rien ne se passe comme prévu. L’option Ignore insert errors, qui fait ignorer les erreurs d’insertion telles que les clés violées, n’est pas disponible pour les insertions en mode batch. Or Use batch update for inserts est active par défaut, précisément parce qu’elle limite les allers-retours vers la base. La documentation précise au passage qu’au maximum 20 avertissements seront journalisés.
Il faut donc choisir : conserver le mode batch et écarter les doublons en amont, avec un lookup ou un Data Validator ; ou désactiver le batch pour un rejet ligne à ligne, en acceptant la perte de débit. Sur un chargement volumineux, la première option gagne presque toujours.
6. Décider quand un pipeline doit vraiment s’arrêter
Certaines situations ne se rattrapent pas. Fichier source vide, référentiel non chargé, devise inconnue : poursuivre reviendrait à publier des chiffres faux, ce qui est pire que ne rien publier du tout.
Le transform Abort répond à ce besoin : il arrête un pipeline dès qu’il reçoit des données en entrée. On le branche derrière un Filter Rows qui isole la condition inacceptable. Abort threshold fixe après combien de lignes déclencher l’arrêt (0 signifie dès la première), Abort message définit le message journalisé, Always log rows force la journalisation des lignes concernées quel que soit le niveau de log. Trois comportements sont proposés : Abort the running pipeline, Abort and log as an error, et Stop input processing, qui interrompt les transforms d’entrée tout en laissant traiter les enregistrements déjà lus. Retenez la nuance : seul Abort and log as an error fait remonter un statut d’échec, et c’est celui qu’il vous faut si un workflow parent doit réagir.
Au niveau du workflow, l’équivalent est l’action Abort workflow, qui arrête immédiatement l’exécution et la marque toujours comme en échec, quel que soit le statut des actions précédentes. Elle accepte un Message et un Log level of the message, dont la valeur par défaut est Error.
7. Câbler le tout dans un workflow
La chaîne prend alors sa forme définitive. Le workflow appelle le pipeline de chargement par une action Pipeline. Du hop vert part la suite normale du traitement ; du hop orange, la branche d’incident : une action Mail qui prévient l’équipe, puis un Abort workflow qui garantit un code de retour en échec. C’est ce dernier point qui rend le dispositif utilisable par un ordonnanceur : que vous lanciez le workflow par hop-run ou par un service HTTP de Hop Server, c’est ce statut qui fera passer votre job Jenkins au rouge ou déclenchera la reprise dans Airflow.
./hop-run.sh \
-j facturation \
-e facturation-prod \
-r local \
-f ${PROJECT_HOME}/workflows/chargement-nocturne.hwf \
-l BASIC
L’option -l (--level) accepte NOTHING, ERROR, MINIMAL, BASIC, DETAILED, DEBUG et ROWLEVEL. Restez en BASIC en production : votre diagnostic est désormais dans le fichier de rejets, pas dans le log.
Ce que vous avez gagné
Une ligne mal formée ne fait plus tomber un chargement. Les enregistrements écartés sont conservés avec leur motif de rejet, dans un fichier transmissible tel quel. Un seuil alerte quand le taux d’anomalies sort de l’ordinaire, et non dès la première ligne. Et les cas réellement bloquants provoquent un échec explicite, visible depuis votre ordonnanceur, au lieu d’un succès silencieux sur des données incomplètes.
C’est aussi la condition d’un travail serein sur la suite : une fois les erreurs canalisées, les tests unitaires de pipelines deviennent exploitables, puisque vous distinguez enfin un pipeline qui échoue d’un pipeline qui rejette.
Pour aller plus loin
- Pipeline Error Handling — le mécanisme et tous les champs de la boîte de dialogue
- Data Validator — la liste complète des règles de validation disponibles
- Abort — les options d’arrêt d’un pipeline
- Abort workflow — l’équivalent au niveau de l’orchestration
- Workflows — les statuts de sortie et les couleurs de hops
- Pipeline Unit Testing — la suite logique de cet article