> ## Documentation Index
> Fetch the complete documentation index at: https://docsmlx.otterly.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Erreurs & guardrails

> Gérer proprement les erreurs de génération et de tool calling

Les erreurs ne sont pas un cas marginal. Dans une app réelle, vous devez prévoir :

* l'indisponibilité du modèle
* les prompts concurrents
* les réponses structurées qui échouent à se décoder
* les refus ou blocages de sécurité
* les erreurs de vos tools

***

## Les erreurs les plus utiles à connaître

| Erreur                        | Ce que vous devez faire                                  |
| ----------------------------- | -------------------------------------------------------- |
| `assetsUnavailable`           | Vérifier la disponibilité du modèle et proposer un retry |
| `concurrentRequests`          | Empêcher les doubles envois                              |
| `decodingFailure`             | Simplifier le type généré ou le prompt                   |
| `exceededContextWindowSize`   | Créer une nouvelle session ou raccourcir l'entrée        |
| `guardrailViolation`          | Afficher un message clair et demander une reformulation  |
| `rateLimited`                 | Réessayer plus tard                                      |
| `refusal`                     | Expliquer que le modèle n'a pas répondu                  |
| `unsupportedGuide`            | Corriger les guides côté développement                   |
| `unsupportedLanguageOrLocale` | Vérifier la locale prise en charge                       |

***

## Un pattern de base en SwiftUI

```swift theme={null}
import FoundationModels
import Observation

@Observable
@MainActor
final class AIViewModel {
    var output = ""
    var errorMessage: String?

    private let session = LanguageModelSession()

    func run(prompt: String) async {
        errorMessage = nil

        do {
            let response = try await session.respond(to: prompt)
            output = response.content
        } catch let error as LanguageModelSession.GenerationError {
            switch error {
            case .concurrentRequests:
                errorMessage = "Une réponse est déjà en cours."
            case .exceededContextWindowSize:
                errorMessage = "La conversation est devenue trop longue. Recommencez une nouvelle session."
            case .guardrailViolation:
                errorMessage = "Cette demande ne peut pas être traitée telle quelle."
            case .unsupportedLanguageOrLocale:
                errorMessage = "La langue actuelle n'est pas prise en charge."
            default:
                errorMessage = "La génération a échoué. Réessayez."
            }
        } catch {
            errorMessage = "Erreur inattendue : \(error.localizedDescription)"
        }
    }
}
```

***

## Guardrails : ce que ça implique pour l'UI

Les guardrails sont intégrés au modèle. Vous ne définissez pas vos propres règles, mais Apple expose tout de même des profils prêts à l'emploi.

```swift theme={null}
import FoundationModels

let defaultModel = SystemLanguageModel(
    useCase: .general,
    guardrails: .default
)

let transformationModel = SystemLanguageModel(
    useCase: .general,
    guardrails: .permissiveContentTransformations
)
```

`.default` reste le choix normal. `.permissiveContentTransformations` vise surtout les cas où vous transformez un texte fourni par l'utilisateur, même si ce texte peut contenir du contenu sensible.

Côté produit, cela signifie :

* ne promettez pas que le modèle répondra à tout
* prévoyez un message de reformulation
* évitez d'afficher des erreurs techniques brutes

Le bon message utilisateur ressemble souvent à :

```text theme={null}
Cette demande ne peut pas être traitée. Essayez de reformuler.
```

***

## `refusal` n'est pas toujours une erreur spectaculaire

Parfois le modèle lève une erreur. Parfois il produit simplement une réponse de refus. Dans les deux cas, votre app doit rester compréhensible.

Ne basez pas toute votre stratégie uniquement sur une exception.

***

## Gérer les erreurs de tools

Quand un tool échoue, vous pouvez récupérer un `ToolCallError`.

```swift theme={null}
func runWithTools(session: LanguageModelSession) async {
    do {
        let response = try await session.respond(
            to: "Cherche mes prochains rendez-vous."
        )
        print(response.content)
    } catch let error as LanguageModelSession.ToolCallError {
        print("Tool en échec :", error.tool.name)
        print("Cause :", error.underlyingError.localizedDescription)
    } catch {
        print(error.localizedDescription)
    }
}
```

L'intérêt de `ToolCallError` est qu'il vous donne deux informations utiles :

* `tool` pour savoir quelle capacité a échoué
* `underlyingError` pour garder la vraie cause technique

Si votre tool parle à une base locale ou à un backend, fournissez des erreurs métier lisibles avec `LocalizedError`.

***

## Ce qu'il faut faire dans l'app

* bloquer les doubles envois avec `isResponding`
* différencier erreur technique et message utilisateur
* réinitialiser la session si le contexte devient trop long
* prévoir un fallback si le modèle n'est pas disponible

Une bonne gestion d'erreur protège autant la stabilité de l'UI que la perception de qualité.

***

<CardGroup cols={2}>
  <Card title="Streaming & UX" icon="bolt" href="/mlx/foundation-models/streaming-ux">
    Voir comment intégrer la génération dans l'interface.
  </Card>

  <Card title="Patterns d'architecture" icon="sitemap" href="/mlx/foundation-models/architecture-patterns">
    Choisir les bons patterns dès le départ.
  </Card>
</CardGroup>
