[Index de la documentation](https://prescriptio.fr/docs/llms.txt)

# Codes d'erreur

Une erreur de Prescriptio dit ce qui s'est passé et quoi faire : le connecteur MCP renvoie une erreur JSON-RPC quand l'appel est impossible, et une erreur métier lisible par le modèle quand l'action n'a pas abouti ; l'API REST renvoie les mêmes cas en codes HTTP.

## Les deux familles d'erreurs

- **Erreur JSON-RPC** (champ `error`) : l'appel n'a pas pu avoir lieu (requête illisible, outil inconnu, portée absente, quota, dépendance indisponible).
- **Erreur d'outil** (`result.isError: true`) : l'outil a été appelé, mais l'action n'a pas abouti. Un argument absent ou hors schéma arrive ainsi, avec un message en français qui nomme l'argument et dit quoi corriger : le modèle le lit et se reprend.

## Connecteur MCP

| Code | Quand | Que faire |
|---|---|---|
| `-32700` | Le corps n'est pas un JSON lisible | Corriger le JSON envoyé |
| `-32600` | Requête invalide : envoi groupé, champ `method` absent, corps de plus de 3 Mio | Un appel par requête, un corps plus léger |
| `-32001` | Jeton absent, expiré ou révoqué (réponse HTTP `401` avec `WWW-Authenticate`) | Relancer l'autorisation OAuth |
| `-32601` | La méthode ou l'outil demandé n'existe pas à cette adresse | Appeler `tools/list` ; ne jamais deviner un nom |
| `-32003` | La portée OAuth manque à l'autorisation | Reconnecter en acceptant `mcp:read`, ou `mcp:write` pour écrire ; le refus nomme la portée, jamais une offre |
| `-32004` | Le quota par minute ou le quota journalier est atteint | Lire le message : attendre le délai indiqué, ne jamais boucler |
| `-32603` | Une dépendance ne répond pas | Réessayer plus tard ; ne pas rejouer une écriture sans vérifier qu'elle n'a pas eu lieu |

`-32602` ne sert qu'à la lecture d'une ressource (`resources/read`) : adresse absente, inconnue ou indisponible. Un appel d'outil ne le rend jamais.

## API REST

Le corps d'une erreur porte `error.code`, `error.message`, `error.retry_after_seconds` quand le délai est connu, et `api_contract_version`.

| HTTP | `error.code` | Que faire |
|---|---|---|
| `400` | `invalid_arguments`, `invalid_cursor` | Corriger l'argument ; reprendre le curseur tel qu'il a été rendu |
| `400` | `invalid_json`, `invalid_body` | Envoyer un corps JSON lisible |
| `401` | `unauthenticated` | Obtenir un nouveau jeton |
| `403` | `insufficient_scope` | Redemander l'autorisation avec la portée nommée |
| `403` | `access_denied`, `user_required`, `organization_required`, `role_denied` | L'action exige un utilisateur, une organisation ou un rôle que le jeton n'a pas |
| `403` | `origin_denied` | L'appel vient d'un navigateur dont l'origine n'est pas autorisée |
| `404` | `not_found` | L'opération ou l'objet est introuvable dans votre espace |
| `405` | `method_not_allowed` | Appeler l'opération en `POST` |
| `408` | `invalid_body` | Le corps n'est pas arrivé en 30 secondes : renvoyer |
| `409` | `conflict` | L'action entre en conflit avec l'état de l'objet |
| `413` | `invalid_body` | Alléger le corps : 3 Mio au plus |
| `415` | `unsupported_media_type` | Envoyer `Content-Type: application/json` |
| `429` | `quota_exceeded` | Attendre `Retry-After` quand il est donné ; lire le message |
| `503` | `unavailable`, `quota_unavailable` | Réessayer plus tard |
| `504` | `timeout` | L'opération a dépassé 35 secondes ; vérifier avant de rejouer une écriture |

```json
{
  "error": {
    "code": "quota_exceeded",
    "message": "<message en français>",
    "retry_after_seconds": 60
  },
  "api_contract_version": "3.0.0"
}
```

## Les trois refus de quota

1. **« Quota par minute atteint »**

   Un frein passager, au-delà de 5 appels par minute (30 pour un abonné). Attendez une minute et reprenez, un appel à la fois. L'abonnement n'est pas la réponse.

2. **« Quota journalier atteint »**

   Le plafond des 24 heures glissantes (100 appels, ou 5 000 pour un abonné). L'abonnement relève ce plafond ; l'analyse du rapport de marque lui est aussi réservée. Les outils d'aide et d'abonnement restent soumis au quota d'appels : s'il est épuisé, ouvrez directement [Paramètres › Abonnement](https://prescriptio.fr/parametres?tab=abonnement), ou attendez que la fenêtre se libère.

3. **« Quota de consultation atteint »**

   Les dossiers ouverts aujourd'hui (5, ou 500 pour un abonné). Le compteur repart à minuit, heure de Paris, et un dossier déjà ouvert se relit sans compter. Chercher n'entre pas dans ce compte, seulement dans le quota d'appels ; l'abonnement relève ce plafond.

Sur `/api/mcp`, les deux premiers refus arrivent généralement en erreur `-32004` ; le troisième arrive comme une erreur d'outil (`isError`), puisque c'est l'outil de lecture qui compte les dossiers. Un outil passant par le traitement des intégrations peut aussi rendre son refus dans `isError`. Le profil `/api/mcp/connectors` rend les erreurs de ses opérations dans `isError`, avec le détail dans `_meta["prescriptio/error"]`. Par l'API REST, les trois rendent `429 quota_exceeded`.

## Tester un jeton

`GET /api/mcp/v1/me` répond sans donnée personnelle : le jeton est-il valable, avec quelle offre et quelles portées.

```bash
curl -sS https://prescriptio.fr/api/mcp/v1/me -H 'Authorization: Bearer <jeton>'
```

```json
{ "authenticated": true, "tier": "<offre>", "scope": "<portées>" }
```

> **Attention :** Un message d'erreur n'est jamais une donnée : ne le recopiez pas comme un fait, et n'inventez pas un identifiant ou une adresse qu'il ne contient pas.

- [Authentification et quotas](https://prescriptio.fr/docs/reference/authentification) : Les portées et les plafonds, par offre
- [Dépannage du connecteur](https://prescriptio.fr/docs/ia/depannage) : 401, portée manquante, quota, limite par minute
