Skip to content

Erreurs ​

Quand l'API refuse une requête, elle répond toujours de la même façon : un statut HTTP, une phrase en anglais pour les humains, et un code stable pour les programmes.

Pourquoi un code, et pas seulement une phrase ? ​

Le site et l'application affichent leurs messages en français ou en anglais. S'ils reconnaissaient les erreurs à leur phrase anglaise, une simple faute corrigée dans l'API (« has already been taken » devenu « is already taken ») casserait silencieusement leur traduction.

Le code, lui, ne change jamais : week_validated restera week_validated. Chaque client le traduit dans sa langue. C'est le même principe que les API de GitHub ou de Google, et la norme RFC 9457.

Les trois formes de réponse ​

Une erreur générale (400, 401, 403, 409) ​

json
{ "error": "week validated", "code": "week_validated" }

Des valeurs refusées (422) ​

Une erreur par champ, avec ses paramètres quand le message en a besoin :

json
{
  "errors":  { "end_date": ["must be less than 31 days after the start date"] },
  "details": { "end_date": [{ "code": "too_long", "max": 31 }] }
}
  • errors : les phrases anglaises, pour les développeurs et les journaux ;
  • details : le contrat pour les clients, un code par erreur et ses paramètres (count, max). Le site affiche « La date de fin doit être à moins de 31 jours du début » à partir de too_long et max: 31.

Une ressource introuvable (404) ​

json
{ "error": "user not found", "code": "not_found" }

Pour un identifiant inconnu dans une route générique, Phoenix répond aussi avec sa forme par défaut : {"errors": {"detail": "Not Found"}}.

D'où viennent les erreurs ​

  • Plugs.Authenticate répond lui-même 401 quand personne n'est connecté.
  • Tout le reste passe par FallbackController : le {:error, …} sorti du with d'un contrôleur y devient une réponse.
  • Un changeset refusé passe par ChangesetJSON, qui produit errors et details.

Le code d'une erreur 422 vient d'Ecto quand la règle est une validation standard (validate_required donne required, une contrainte d'unicité taken…), ou de l'option code: quand la règle est écrite à la main :

elixir
add_error(changeset, :start, "overlaps another working time", code: :overlaps)

Tous les codes ​

Erreurs générales ​

CodeStatutQuand
bad_request400paramètres illisibles (une date mal écrite, un corps manquant)
unauthorized401personne n'est connecté, session expirée, mauvais identifiants
forbidden403connecté, mais pas le droit (voir Droits par rôle)
not_found404la ressource n'existe pas
conflict409une règle des données refuse l'action (révoquer un manager qui a encore une équipe, rouvrir une semaine déjà rouverte…)
week_validated409la semaine est validée : ses heures, absences et demandes sont verrouillées
already_clocked_in409« arrivée » alors que la personne est déjà arrivée
not_clocked_in409« départ » ou pause alors que la personne n'est pas arrivée
already_on_break409« début de pause » pendant une pause
not_on_break409« fin de pause » sans pause en cours

Valeurs refusées (422, dans details) ​

Les validations standard d'Ecto

CodeSens
requiredchamp obligatoire manquant
takenvaleur déjà utilisée (un e-mail, un nom d'équipe, une semaine déjà validée…)
too_short, too_longlongueur hors limites (avec count ou max)
invalid_choicevaleur hors de la liste permise (un rôle, une action inconnue…)
invalid_formatformat refusé (un e-mail sans @)
invalidtype impossible à lire (un UUID mal formé, une date invalide)

Les règles du métier

CodeChampQuand
in_futureend, work_date, timeune heure ou une date qui n'est pas encore arrivée
not_after_startendune fin avant le début (journée, pause)
overlapsstart, breaksdeux journées d'une personne, ou deux pauses, se chevauchent
outsidebreaksune pause hors de sa journée
incompletebreaksune pause sans début ou sans fin
too_oldwork_date, timeune correction de plus de 4 semaines, une heure envoyée par le téléphone de plus de 72 h (avec max)
out_of_ordertimeune heure du téléphone avant le pointage ou la pause précédente
before_startend_dateune absence qui finit avant de commencer
no_weekdayend_dateune période d'absence sans aucun jour de semaine
not_mondayweek_startune semaine doit commencer un lundi
not_overweek_starton ne valide qu'une semaine terminée
not_activeuser_idajouter à une équipe un compte encore invité
not_a_managermanager_idnommer à la tête d'une équipe quelqu'un qui n'est pas manager
wrong_passwordcurrent_passwordle mot de passe actuel est faux
same_as_currentemailla nouvelle adresse est déjà celle du compte
use_email_linkemaill'e-mail ne se change pas ici : par le lien envoyé à la nouvelle adresse
general_managerrolele rôle du General Manager ne se change pas
no_uppercasepasswordle mot de passe n'a pas de majuscule
no_specialpasswordle mot de passe n'a pas de caractère spécial

Retrouver un code dans le code

grep -rn "code: :overlaps" timemanager-api/lib donne la règle exacte qui produit overlaps. La page Swagger (/api/docs) montre aussi, pour chaque route, les statuts qu'elle peut renvoyer.

Côté clients ​

ClientLire le code
Site weberrorCode(error) pour une erreur générale, errorDetail(error, 'champ') pour une valeur refusée (src/utils/api.js)
Application mobilevoir Parler à l'API

Ajouter une règle

Toute nouvelle règle écrite à la main doit avoir son code:, ajouté à cette page. Un client ne doit jamais comparer la phrase anglaise.