# Gestion des erreurs

## Convention GraphQL

[Les spécifications GraphQL](https://spec.graphql.org/June2018/#sec-Response-Format) précisent le format général de retour des erreurs : lorsque une requête cause une ou plusieurs erreurs la réponse JSON contiendra un champ `errors`, qui sera une liste non vide des erreurs recontrées.

Si la requête a donné lieu à une exécution la réponse contiendra également un champ `data`, comme dans le cas d'une requête sans erreurs.

On peut distinguer 3 types d'erreurs :

* les erreurs de syntaxe
* les erreurs de schéma
* les erreurs applicatives, qui arrivent pendant l'exécution de la requête

Les erreurs de syntaxe et les erreurs de schéma bloquent l'exécution de la requête : la réponse ne contiendra pas de champ `data`.

## Erreurs de syntaxe <a href="#erreurs-de-syntaxe" id="erreurs-de-syntaxe"></a>

Les erreurs de syntaxe recouvrent toutes les erreurs qui empêchent le parser GraphQL d'interpréter la requête. Le code HTTP de la réponse sera toujours `400`.

On y trouve par exemple les erreurs dans la constitution du JSON :

```http
POST /api/graphql HTTP/1.1
Host: sandbox.mobilic.beta.gouv.fr
Content-Type: application/json

{"Mauvais JSON"}
```

qui donnera cette réponse :

```http
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json

{
  "errors": [
    {
      "message":"POST body sent invalid JSON."
    }
  ]
{
```

Il y a également les erreurs de syntaxe GraphQL :

```http
POST /api/graphql HTTP/1.1
Host: sandbox.mobilic.beta.gouv.fr
Content-Type: application/json

{
  "query": "wrongKeyword"
}
```

Réponse :

```http
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json

{
  "errors": [
    {
      "message":"Syntax Error GraphQL (1:1) Unexpected Name \"wrongKeyword\"\n\n1: wrongKeyword\n   ^\n",
      "locations": [
        {
          "line":1,
          "column":1
        }
      ]
    }
  ]
}
```

{% hint style="info" %}
Dans la [console](https://mobilic.beta.gouv.fr/developers/docs/playground) les erreurs de syntaxe sont détectées en direct et empêchent la requête d'être soumise à l'API.
{% endhint %}

## Erreurs de schéma <a href="#erreurs-de-schema" id="erreurs-de-schema"></a>

Les erreurs de schéma concernent les requêtes syntaxiquement correctes mais qui ne respectent pas le schéma des opérations.

Comme la syntaxe est correcte nous ne montrons dans la suite que l'opération GraphQL plutôt que de montrer tout le corps de la requête HTTP. Pour rappel le passage de l'opération GraphQL à la requête `POST` HTTP est expliqué [ici](/guides/effectuer-une-requete-a-lapi.md#exemple-simple).

Comme pour les erreurs de syntaxe le code HTTP de la réponse est `400`.

Exemple

```graphql
query {
  wrongOperation {
    someField
  }
}
```

Réponse

```json
{
  "errors": [
    {
      "message": "Cannot query field \"wrongOperation\" on type \"Queries\".",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ]
    }
  ]
}
```

### Erreurs de validation des variables <a href="#erreurs-de-validation-des-variables" id="erreurs-de-validation-des-variables"></a>

Les erreurs de type sur les variables d'opération sont également considérées comme des erreurs de schéma et donnent lieu aux mêmes réponses.

Exemple

```graphql
query {
  user(id: "pas un entier") {
    firstName
  }
}
```

Réponse

```json
{
  "errors": [
    {
      "message": "Argument \"id\" has invalid value \"pas un entier\".\nExpected type \"Int\", found \"pas un entier\".",
      "locations": [
        {
          "line": 2,
          "column": 12
        }
      ]
    }
  ]
}
```

{% hint style="warning" %}
Dans la [console](https://mobilic.beta.gouv.fr/developers/docs/playground) la réponse retournée par l'API à une requête qui cause une erreur de schéma se retrouve à l'affichage encapsulée dans un champ supplémentaire `error`.
{% endhint %}

## Erreurs applicatives <a href="#erreurs-applicatives" id="erreurs-applicatives"></a>

Les erreurs applicatives désignent toutes les erreurs qui arrivent lors de l'exécution de la requête.

Le code HTTP de la réponse est `200` pour ce type d'erreurs.

### Résultats partiels <a href="#resultats-partiels" id="resultats-partiels"></a>

Lorsque des erreurs arrivent à l'exécution la réponse comporte également un champ `data`, qui peut contenir des résultats partiels, en fonction des endroits où sont apparues les erreurs.

Exemple

```graphql
query {
  company(id: 1) {
    id
    name
    missions {
      id
    }
  }
}
```

Réponse

```json
{
  "errors": [
    {
      "message": "Unauthorized access to field 'missions' of company object. Actor must be company admin.",
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ],
      "path": ["company", "missions"],
      "extensions": {
        "code": "AUTHORIZATION_ERROR"
      }
    }
  ],
  "data": {
    "company": {
      "id": 8,
      "name": "Mobilic Team",
      "missions": null
    }
  }
}
```

Dans le cas ci-dessus la réponse a retourné des résultats partiels car une partie de l'opération n'a pas déclenché d'erreur. Pour les parties qui causent des erreurs le champ correspondant dans la réponse aura toujours la valeur `null`.

### Codes erreurs <a href="#codes-erreurs" id="codes-erreurs"></a>

Chaque erreur applicative comprend un code, situé dans le champ `extensions.code` de l'erreur. Ces codes servent à classer les erreurs. Voici la liste des codes :&#x20;

#### Erreurs d'authentification et de sécurité

| Code                           | Description                                                                              | Sévérité |
| ------------------------------ | ---------------------------------------------------------------------------------------- | -------- |
| `AUTHENTICATION_ERROR`         | Données d'authentification manquantes ou invalides (token expiré, clé API invalide)      | Critique |
| `AUTHORIZATION_ERROR`          | Permissions insuffisantes pour accéder à la ressource ou effectuer l'opération           | Haute    |
| `INVALID_TOKEN`                | Token d'invitation invalide pour le rattachement à une entreprise                        | Haute    |
| `BLOCKED_ACCOUNT_ERROR`        | Le compte utilisateur est bloqué                                                         | Haute    |
| `BAD_PASSWORD_ERROR`           | Mot de passe incorrect lors de la connexion                                              | Moyenne  |
| `ACTIVATION_EMAIL_DELAY_ERROR` | Délai minimum entre deux envois d'email d'activation non respecté (protection anti-spam) | Basse    |
| `UNSUPPORTED_ALGORITHM_ERROR`  | Algorithme de cryptographie non supporté                                                 | Haute    |

#### Erreurs d'intégration SSO

| Code                                                | Description                                           | Sévérité |
| --------------------------------------------------- | ----------------------------------------------------- | -------- |
| `FRANCE_CONNECT_ERROR`                              | Erreur lors de l'authentification via FranceConnect   | Haute    |
| `FRANCE_CONNECT_V2_ERROR`                           | Erreur spécifique à FranceConnect v2                  | Haute    |
| `AGENT_CONNECT_ERROR`                               | Erreur lors de l'authentification via AgentConnect    | Haute    |
| `AGENT_CONNECT_ORGANIZATIONAL_UNIT_NOT_FOUND_ERROR` | Unité organisationnelle non trouvée dans AgentConnect | Moyenne  |

#### Erreurs de validation des données

| Code                  | Description                                                                                     | Sévérité |
| --------------------- | ----------------------------------------------------------------------------------------------- | -------- |
| `INVALID_INPUTS`      | Valeurs incorrectes pour les variables de l'opération GraphQL                                   | Basse    |
| `BAD_REQUEST`         | Requête HTTP invalide (erreur 400)                                                              | Moyenne  |
| `BAD_GRAPHQL_REQUEST` | Requête GraphQL mal formée ou ne respectant pas le schéma                                       | Moyenne  |
| `INVALID_RESOURCE`    | Impossible d'effectuer l'opération demandée sur cet objet (ressource dans un état incompatible) | Moyenne  |

#### Erreurs métier - Entreprises

| Code                          | Description                                               | Sévérité |
| ----------------------------- | --------------------------------------------------------- | -------- |
| `SIRET_ALREADY_SIGNED_UP`     | Ce SIRET est déjà inscrit sur Mobilic                     | Moyenne  |
| `SIREN_ALREADY_SIGNED_UP`     | Ce SIREN est déjà inscrit sur Mobilic                     | Moyenne  |
| `COMPANY_HAS_CEASED_ACTIVITY` | L'entreprise a cessé son activité selon les données INSEE | Moyenne  |

#### Erreurs métier - Missions et activités

| Code                      | Description                                                                                   | Sévérité |
| ------------------------- | --------------------------------------------------------------------------------------------- | -------- |
| `OVERLAPPING_MISSIONS`    | Chevauchement temporel de deux missions pour un même travailleur mobile                       | Moyenne  |
| `OVERLAPPING_ACTIVITIES`  | Chevauchement temporel de deux activités pour un même travailleur mobile                      | Moyenne  |
| `MISSION_ALREADY_ENDED`   | Tentative de modification d'une mission déjà terminée pour le travailleur                     | Moyenne  |
| `INVALID_ACTIVITY_SWITCH` | Échec de l'enregistrement en mode tachygraphe en raison d'entrées chronologiques incohérentes | Basse    |
| `DUPLICATE_EXPENDITURES`  | Tentative d'enregistrement de frais déjà existants sur une mission                            | Basse    |

#### Erreurs métier - Emplois et rattachements

| Code                      | Description                                                                      | Sévérité |
| ------------------------- | -------------------------------------------------------------------------------- | -------- |
| `OVERLAPPING_EMPLOYMENTS` | Chevauchement temporel de deux rattachements entreprise pour un même salarié     | Moyenne  |
| `NO_PRIMARY_EMPLOYMENT`   | Absence de rattachement principal (requis pour créer un rattachement secondaire) | Moyenne  |

#### Erreurs système

| Code                    | Description                                         | Sévérité |
| ----------------------- | --------------------------------------------------- | -------- |
| `INTERNAL_ERROR`        | Erreur interne côté serveur Mobilic                 | Critique |
| `INTERNAL_SERVER_ERROR` | Erreur serveur interne (variante d'INTERNAL\_ERROR) | Critique |

#### Guide de sévérité

* **Critique** : Nécessite une intervention immédiate, bloque toute utilisation
* **Haute** : Impact important sur les fonctionnalités, investigation rapide requise
* **Moyenne** : Erreur métier à corriger, ne bloque pas l'utilisation générale
* **Basse** : Information ou avertissement, peut être traité ultérieurement


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.mobilic.beta.gouv.fr/guides/gestion-des-erreurs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
