Erreurs
Les codes d’erreur stables de la bibliothèque, du protocole et de la page de livraison, et quoi en faire.
colis a trois familles d’erreurs, chacune avec un code stable sur lequel brancher plutôt que sur un
statut HTTP ou le texte d’un message.
Dans la bibliothèque : ColisError
Tout ce que lève @colis/core est une ColisError, avec un code et l’erreur d’origine dans
cause :
import { isColisError } from '@colis/core'
try {
await store.upload(file)
} catch (error) {
if (isColisError(error)) console.error(error.code, error.message, error.cause)
throw error
}| Code | Quand |
|---|---|
INVALID_CONFIG | Bucket manquant, publicUrl qui n’est pas une URL absolue, maxSize non positif, forme de code invalide. |
INVALID_SYNC_CODE | Le code est vide, ou contient un caractère hors de l’alphabet. |
INVALID_KEY | Clé vide, / en début ou en fin, segment .., antislash, caractère de contrôle, plus de 1 024 octets. |
INVALID_BODY | Le corps envoyé n’est pas d’un type pris en charge. |
MISSING_CONTENT_LENGTH | Un flux envoyé sans contentLength. |
FILE_TOO_LARGE | Le corps dépasse maxSize. |
UPLOAD_FAILED | PutObject ou un envoi en morceaux a été refusé. Erreur d’origine dans cause. |
GET_FAILED | GetObject ou HeadObject a échoué pour une autre raison qu’une clé absente. |
DELETE_FAILED | DeleteObject ou DeleteObjects a été refusé, ou S3 a signalé des échecs par clé. |
URL_FAILED | expiresIn invalide, échec de signature, ou URL publique demandée sans publicUrl. |
PRECONDITION_FAILED | Une écriture ifMatch ou ifAbsent a perdu la course. |
INVALID_SNAPSHOT | Un enregistrement JSON illisible, ou des données que JSON ne sait pas représenter. |
SNAPSHOT_TOO_NEW | Un enregistrement écrit par un schéma plus récent que maxVersion. |
INVALID_CONFIG, INVALID_SYNC_CODE, INVALID_KEY, INVALID_BODY, MISSING_CONTENT_LENGTH et
FILE_TOO_LARGE sont levées avant qu’un seul octet ne parte : un code absurde collé dans un champ
coûte une comparaison, pas une requête.
Une clé absente n’est pas une erreur : get(), head() et getSnapshot() renvoient null, et
delete() sur une clé absente réussit sans bruit.
Sur le fil : TransferError
Les routes du protocole répondent { error: { code, message } }, et
le client de @colis/protocol (donc la CLI, les hooks React et le nœud n8n) lève une
TransferError avec ce code : INVALID_REQUEST, INVALID_SYNC_CODE, UNAUTHORIZED, NOT_FOUND,
CODE_TAKEN, SNAPSHOT_TOO_NEW, TOO_LARGE, INTERNAL.
import { isTransferError } from '@colis/protocol'
if (isTransferError(error) && error.code === 'NOT_FOUND') {
// code inconnu ou expiré : les deux sont indiscernables, exprès
}Sur la page de livraison
Ses routes propres gardent la même forme de réponse, avec quelques codes en plus :
| Code | HTTP | Quand |
|---|---|---|
UNAUTHORIZED | 401 | DROP_PASSWORD manquant ou faux à l’envoi, ou colis protégé sans son mot de passe. L’en-tête x-drop-protected: 1 distingue le second cas. |
FORBIDDEN | 403 | L’expéditeur essaie de répondre à la place du client. |
NOT_FOUND | 404 | Code inconnu ou expiré, colis à usage unique déjà téléchargé, ou aucun accusé. |
ALREADY_DECIDED | 409 | Le colis a déjà reçu une réponse ; elle est définitive. |
TOO_LARGE | 413 | Fichier au-delà de DROP_MAX_SIZE_MB en une requête, ou de DROP_MAX_UPLOAD_MB en morceaux (DROP_OPEN_MAX_UPLOAD_MB sans mot de passe). |
RATE_LIMITED | 429 | Trop de mauvais mots de passe (le code est verrouillé), ou, sans DROP_PASSWORD, trop d’envois depuis une adresse (DROP_UPLOADS_PER_HOUR). retry-after dit combien de secondes. |
Les routes des comptes ajoutent les leurs :
| Code | HTTP | Quand |
|---|---|---|
ACCOUNTS_DISABLED | 503 | Le déploiement n’a pas d’e-mail configuré (RESEND_API_KEY, COLIS_MAIL_FROM) : personne ne se connecte. |
UNAUTHENTICATED | 401 | Aucune session sur GET /api/me, ou confirmation d’un code de terminal sans être connecté. |
INVALID_SESSION | 401 | Un jeton Bearer colis_… inconnu, expiré ou révoqué, y compris sur un envoi : jamais d’envoi anonyme à la place. |
INVALID_LINK | 400 | Un lien de connexion déjà utilisé ou expiré (15 minutes). |
INVALID_DEVICE_CODE | 400 | Un code de terminal inconnu, expiré (10 minutes) ou déjà échangé. |
FORBIDDEN_ORIGIN | 403 | Une requête qui modifie la session depuis un autre site que le déploiement. |
MAIL_FAILED | 502 | Resend a refusé l’e-mail, ou n’a pas répondu. |
La formule Pro ajoute les siens :
| Code | HTTP | Quand |
|---|---|---|
PLAN_LIMIT | 403 | Un envoi au-delà de la formule gratuite que Pro accepterait : fichier trop gros, ou durée trop longue. details dit laquelle : { limit, max, pro }. |
BILLING_DISABLED | 503 | Le déploiement ne vend pas Pro : une des quatre variables STRIPE_* manque, ou les comptes sont désactivés. |
ALREADY_PRO | 409 | Un paiement demandé pour un compte déjà Pro. |
NO_SUBSCRIPTION | 404 | L’espace d’abonnement demandé pour un compte qui n’a jamais souscrit. |
BILLING_FAILED | 502 | Stripe a refusé la demande, ou n’a pas répondu. |
INVALID_SIGNATURE | 400 | Un webhook dont la signature Stripe-Signature ne correspond pas, ou date de plus de cinq minutes. |
{
"error": {
"code": "PLAN_LIMIT",
"message": "Ce fichier dépasse 100 Mo, la limite de la formule gratuite. La formule Pro accepte jusqu’à 2 Go.",
"details": { "limit": "size", "max": 104857600, "pro": 2147483648 }
}
}Les messages de ces routes sont en français, prêts à être affichés au client.
Dans la CLI
La CLI sort avec le code 1 à chaque échec, et distingue ce qu’il faut faire :
- une erreur d’usage (commande inconnue, fichier absent, bucket non configuré) s’affiche avec une piste de correction en dessous ;
- une erreur du protocole ou de la bibliothèque s’affiche avec son code, par exemple
NOT_FOUND: Unknown or expired code.; INVALID_CONFIGrappelle quecolis configmontre ce que la configuration a résolu ;PLAN_LIMITrappelle que la formule Pro va plus loin :colis compte pro.
En cas de doute, colis verifier effectue chaque opération et dit laquelle échoue.