SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-09-13

Ollama : corriger « context deadline exceeded »

L’erreur Ollama « context deadline exceeded » indique un timeout avant la réponse. Identifiez la couche en cause : client, charge, keep_alive ou nginx.

Ce que signifie réellement « context deadline exceeded »

L’erreur Ollama context deadline exceeded signale un délai d’expiration. Une partie du code Go a défini une échéance pour la requête, le modèle n’a pas terminé dans ce délai et l’échéance a expiré. Rien n’a planté et aucun fichier n’est corrompu. Le traitement était encore en cours lorsque le délai a expiré.

Cette formulation vient du package standard Go context. C’est déjà un indice utile. Un client Python basé sur httpx lève plutôt httpx.ReadTimeout. Un navigateur affiche une simple erreur réseau. Si vous lisez exactement ces mots, un programme Go a cessé d’attendre : l’outil en ligne de commande Ollama, le serveur Ollama lui-même ou une application Go qui appelle l’API (interface de programmation d’application).

Cinq couches peuvent définir cette échéance. Elles échouent à des étapes différentes et nécessitent chacune une correction différente. Il faut donc déterminer laquelle a déclenché l’expiration.

  1. Votre client HTTP, qui a attribué à la requête un délai fixe.
  2. Le délai de chargement du modèle du serveur Ollama, qui expire lorsqu’un modèle volumineux est lu sur le disque pour la première fois.
  3. keep_alive, qui décharge le modèle entre les requêtes. L’appel suivant doit donc à nouveau payer le coût du chargement.
  4. Un num_ctx suffisamment volumineux pour que le traitement du prompt dure plusieurs minutes sur une machine utilisant uniquement le CPU.
  5. Un reverse proxy comme nginx ou Traefik, qui coupe la connexion avant qu’Ollama ait répondu.

Examinez cette liste dans l’ordre. Chaque étape ci-dessous élimine une couche possible, afin que vous n’ayez plus à procéder par suppositions.

Reproduire l’appel API pour écarter le proxy

Exécutez la requête directement sur le serveur, auprès d’Ollama, sans proxy intermédiaire.

time curl -s http://127.0.0.1:11434/api/generate -d '{
  "model": "llama3.1:8b",
  "prompt": "Why is the sky blue?",
  "stream": false
}' | head -c 400

curl ne définit aucune limite de temps globale. Il définit uniquement un délai d’expiration de connexion. Cette commande attend donc aussi longtemps qu’Ollama en a besoin. Cela permet de réduire le problème de moitié. Si un corps JSON est renvoyé, Ollama a répondu et le délai vient d’un composant situé en amont. Si cet appel reste bloqué pendant plusieurs minutes, le délai se produit dans Ollama et votre proxy n’est pas en cause.

Envoyez maintenant la même requête via votre URL publique et mesurez sa durée.

curl -s -o /dev/null -w '%{http_code} %{time_total}\n' \
  -X POST https://llm.example.com/api/generate \
  -d '{"model": "llama3.1:8b", "prompt": "hi", "stream": false}'

Un statut 504 affiché après un nombre de secondes anormalement rond, comme 60.0 ou 30.0, indique un délai d’expiration du proxy. Les proxys utilisent des valeurs par défaut arrondies. Un modèle ne termine pas exactement après 60.000 secondes deux fois de suite. Si l’appel direct est refusé immédiatement au lieu de rester lent, le problème concerne l’écoute sur le port et non le délai d’expiration. l’adresse sur laquelle Ollama écoute sur le port 11434 traite ce cas.

Surveillez le journal du serveur pendant l’exécution de la requête

Ouvrez une deuxième session et suivez le journal du service, puis envoyez de nouveau la requête.

journalctl -u ollama --no-pager --follow --pager-end

Un démarrage à froid normal journalise le chargement du modèle, puis le démarrage d’un runner et enfin le traitement de la requête. Un échec du chargement ressemble plutôt à ceci. Cette chaîne identifie le délai d’expiration du chargement propre au serveur :

Error: timed out waiting for llama runner to start - progress 0.00 -

Ce message signifie que le processus du modèle n’a pas fini de démarrer dans le délai imparti par le serveur. La valeur de progression indique jusqu’où il est arrivé. Une valeur de 0.00 signifie que le runner n’a rien signalé avant l’échéance. Cela indique généralement que le fichier est encore en cours de lecture ou que la machine utilise le swap. Pour obtenir plus de détails pendant le chargement, redémarrez le service avec OLLAMA_DEBUG=1 défini, puis recommencez.

Mesurez si le délai vient du chargement ou de la génération

Ollama affiche ses propres durées. Vous n’avez donc pas à deviner l’origine du délai.

ollama run --verbose llama3.1:8b "Why is the sky blue?"

Après la réponse, il affiche total duration, load duration, prompt eval count, prompt eval rate, eval count et eval rate. Exécutez la commande deux fois. Lors de la deuxième exécution, load duration doit devenir presque nul, car le modèle est déjà résident en mémoire. Si ce n’est pas le cas, le modèle est déchargé entre les deux exécutions. C’est le cas keep_alive décrit plus bas.

Les mêmes valeurs sont renvoyées par l’API dans le dernier objet JSON, sous la forme load_duration, prompt_eval_duration et eval_duration. La documentation indique que toutes les durées sont exprimées en nanosecondes. Divisez-les donc par 10^9 pour obtenir des secondes.

curl -s http://127.0.0.1:11434/api/generate -d '{
  "model": "llama3.1:8b",
  "prompt": "Why is the sky blue?",
  "stream": false
}' | python3 -c 'import json,sys; d=json.load(sys.stdin); print({k: round(v/1e9, 2) for k, v in d.items() if k.endswith("_duration")})'

Examinez la valeur la plus élevée. Si load_duration domine, le problème vient du chargement du modèle. Passez aux deux sections suivantes. Si prompt_eval_duration domine, le traitement du prompt est le principal coût. Passez à la section num_ctx. Si eval_duration domine, le modèle génère simplement lentement sur ce matériel. Aucun paramètre de timeout ne changera cela. Réduisez la longueur de la sortie avec num_predict ou utilisez un modèle plus petit.

Augmentez OLLAMA_LOAD_TIMEOUT après avoir vérifié votre version

La variable du serveur qui détermine le délai d’attente avant le démarrage d’un modèle est OLLAMA_LOAD_TIMEOUT. Sa valeur par défaut a changé selon les releases. Consultez donc la valeur correspondant à votre build, et non celle d’un article, y compris celui-ci. Affichez d’abord la version.

ollama --version

Ouvrez ensuite le source correspondant à ce tag précis, https://github.com/ollama/ollama/blob/<your version>/envconfig/config.go, puis recherchez OLLAMA_LOAD_TIMEOUT. La valeur présente dans ce fichier est la valeur par défaut compilée dans votre binaire. Définissez votre propre valeur au moyen d’un systemd drop-in.

sudo systemctl edit ollama.service

Ajoutez les variables sous une section [Service]. C’est la méthode indiquée par la documentation d’Ollama pour Linux :

[Service]
Environment="OLLAMA_LOAD_TIMEOUT=15m"
Environment="OLLAMA_KEEP_ALIVE=-1"
sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment

La dernière commande affiche l’environnement effectivement reçu par le service. Un résultat vide signifie que le drop-in a été enregistré en dehors des marqueurs de l’éditeur ou sous un nom de section incorrect. La valeur définie n’est donc pas appliquée. Comprenez bien ce que cela permet : un délai d’attente plus long empêche le serveur d’abandonner trop tôt, mais n’accélère rien. Si le modèle ne tient pas en mémoire, la machine utilisera le swap, le chargement sera très lent et une valeur plus élevée ne fera que repousser l’échec.

La première requête après une pause est la plus lente

Ollama décharge un modèle inactif pour libérer de la mémoire. Le paramètre keep_alive détermine le délai. La documentation d’Ollama indique une valeur par défaut de 5 minutes, vérifiée en septembre 2026. Une application de chat utilisée une fois par heure recharge donc le modèle à chaque message, et chaque message subit le démarrage à froid complet. La requête qui expire est la première après une période d’inactivité. C’est exactement le comportement que les utilisateurs décrivent comme aléatoire.

Vérifiez les modèles actuellement chargés :

ollama ps
curl -s http://127.0.0.1:11434/api/ps

Une liste vide ou une expiration prévue dans quelques minutes le confirme. keep_alive accepte une chaîne de durée telle que "10m" ou "24h", un nombre indiquant directement des secondes, 0 pour décharger immédiatement le modèle, ainsi qu’un nombre négatif pour le conserver indéfiniment en mémoire. Définissez ce paramètre pour chaque requête ou définissez OLLAMA_KEEP_ALIVE sur le service pour l’appliquer à toutes les requêtes.

curl -s http://127.0.0.1:11434/api/generate -d '{
  "model": "llama3.1:8b",
  "keep_alive": -1
}'

Une requête avec un modèle et sans prompt charge le modèle, puis se termine. C’est la méthode documentée pour préchauffer une machine après un redémarrage. Elle doit être intégrée à une petite unité systemd afin que personne n’attende un démarrage à froid. Le coût est réel : un modèle conservé en mémoire occupe cette mémoire en permanence. Sur une petite machine, vous pouvez donc conserver un modèle, mais pas quatre. Conserver un modèle en mémoire entre les requêtes détaille le calcul de la mémoire et l’unité de préchauffage.

Pourquoi un num_ctx élevé expire avant le premier token

Avant de produire quoi que ce soit, un modèle doit lire l’intégralité de votre prompt. Cette étape s’appelle le prefill. C’est ce que mesure prompt eval. num_ctx définit la longueur du contexte, avec deux effets simultanés. Il limite le nombre de tokens que le modèle peut prendre en compte et dimensionne la KV cache (key value cache) que le serveur alloue au démarrage. Ces deux éléments augmentent la charge de travail.

Sur un serveur uniquement équipé d’un CPU, le prefill est lent et sa durée augmente linéairement avec le nombre de tokens du prompt. Un long document collé dans un chat peut passer plusieurs minutes en prefill sans que le client n’affiche quoi que ce soit, car le streaming n’a pas encore commencé. Le client atteint son délai d’expiration et signale context deadline exceeded, alors que le serveur a travaillé pendant tout ce temps. Vérifiez-le avec les chiffres de la section précédente : exécutez le même prompt avec "options": {"num_ctx": 2048}, puis avec 32768, et comparez prompt_eval_duration.

La valeur par défaut du serveur vient de OLLAMA_CONTEXT_LENGTH. Un num_ctx par requête dans l’objet options la remplace. L’augmenter jusqu’au maximum annoncé par le modèle simplement parce que ce maximum existe est l’erreur la plus courante. L’allocation de la KV cache peut en effet faire sortir le modèle de la RAM et transformer une configuration fonctionnelle en configuration utilisant le swap. Choisir num_ctx en fonction de votre mémoire réelle présente les détails du dimensionnement.

Pourquoi nginx renvoie 504 Gateway Time-out

nginx documente proxy_read_timeout avec une valeur par défaut de 60s, et son error log décrit clairement l’échec :

upstream timed out (110: Connection timed out) while reading response header from upstream

Le point important se trouve dans la documentation nginx : le timeout « s’applique uniquement entre deux opérations de lecture successives, et non à la transmission de l’ensemble de la réponse ». Une réponse en streaming réinitialise le délai à chaque chunk. Les chats en streaming peuvent donc durer. Une requête avec "stream": false n’envoie rien avant que la réponse soit terminée. Toute la génération doit donc s’achever dans cette seule fenêtre. C’est pourquoi le même modèle fonctionne dans la fenêtre de chat, mais expire depuis un script.

location / {
    proxy_pass http://127.0.0.1:11434;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;
    proxy_buffering off;
}
sudo nginx -t && sudo systemctl reload nginx

proxy_buffering off est important pour le streaming. Lorsque le buffering est activé, nginx peut accumuler la réponse et la transmettre à la fin. Les tokens cessent alors d’apparaître un par un, et un flux fonctionnel commence à ressembler à un blocage.

Traefik place le même réglage dans le ServersTransport utilisé par le router.

http:
  serversTransports:
    ollama:
      forwardingTimeouts:
        dialTimeout: "30s"
        responseHeaderTimeout: "0s"
        idleConnTimeout: "60s"

responseHeaderTimeout couvre l’attente des response headers après l’écriture de la requête, et la valeur 0 désactive le timeout. Le service doit référencer le transport par son nom avec serversTransport: ollama. Sinon, vous avez modifié un bloc qui n’est utilisé nulle part.

Une quantification plus légère se charge plus rapidement, car il y a moins de données à lire

La quantification correspond à la précision avec laquelle les poids sont stockés. Une précision moindre produit un fichier plus petit, et le chargement d’un modèle consiste principalement à lire ce fichier depuis le disque pour le placer en mémoire.

ChartPublished download sizes for llama3.1 8B on the ollama.com library, September 2026
The data behind this chart
[
  {
    "label": "q4_K_M",
    "download_size_gb": 4.9
  },
  {
    "label": "q8_0",
    "download_size_gb": 8.5
  },
  {
    "label": "fp16",
    "download_size_gb": 16
  }
]

Ces tailles sont celles publiées sur la page du modèle, et non des mesures effectuées sur un serveur de test. La version 8B par défaut fait 4.9 Go. La version en pleine précision du même modèle fait 16 Go, soit plus de trois fois plus d’octets à lire et plus de trois fois plus de mémoire à mobiliser. Sur un serveur loué avec un stockage partagé, cette différence suffit à faire la distinction entre un chargement qui se termine et un chargement qui expire. Déterminer quel modèle tient dans votre RAM est la vérification à effectuer avant de télécharger un fichier volumineux.

Modifications à apporter sur un serveur loué

Appliquez ces modifications dans l’ordre indiqué par les mesures, une à la fois, puis relancez la commande de mesure après chacune.

  1. Épinglez le modèle avec OLLAMA_KEEP_ALIVE=-1, ou préchargez-le au démarrage, afin qu’aucune requête utilisateur ne paie le coût du chargement.
  2. Réduisez num_ctx à la valeur réellement nécessaire pour vos prompts. Le prefill est ainsi plus court et la mémoire occupée par le cache KV est libérée.
  3. Utilisez une quantification plus petite. Le chargement lit moins d’octets et le modèle laisse davantage de mémoire au cache.
  4. Augmentez proxy_read_timeout dans nginx ou responseHeaderTimeout dans Traefik, puis désactivez le buffering afin que les tokens générés en streaming atteignent le client.
  5. Augmentez le timeout dans votre propre client, car un programme Go ou Python limité à 30 secondes échouera avec tout modèle qui met plus longtemps à répondre.

Une autre cause peut se cacher derrière toutes les précédentes. Ollama ne traite qu’un nombre limité de requêtes simultanément et met les autres en file d’attente. Un deuxième appelant peut donc rester dans la file jusqu’à l’expiration de son propre délai, alors qu’aucun modèle lent n’est en cause. Le journal du serveur indique que la requête a été traitée en retard, plutôt qu’en échec. Ce qui se passe quand plusieurs personnes partagent un même serveur Ollama explique les paramètres de parallélisme, et l’installation de base sur un VPS décrit la configuration du service sur laquelle ces overrides reposent.

FAQ

Que signifie « context deadline exceeded » dans Ollama ?

Cela signifie que le délai imparti à la requête a expiré avant que le modèle ne réponde. Cette expression vient du package Go context. Elle a donc été affichée par un programme Go : l’outil en ligne de commande Ollama, le serveur Ollama ou une application Go qui appelle l’API. Il s’agit d’un délai d’expiration. Rien n’est cassé ni corrompu. Vous devez ensuite déterminer quelle couche a défini ce délai, car le client, le chargement du modèle, keep_alive, num_ctx et le reverse proxy définissent chacun leur propre délai.

Dois-je augmenter le délai d’expiration du client ou celui d’Ollama ?

Commencez par mesurer. Envoyez la requête avec curl directement sur le serveur, vers http://127.0.0.1:11434, car curl n’impose aucune limite de durée globale. Si cet appel renvoie un corps JSON, Ollama répond. Le délai vient donc de votre client ou de votre proxy. Augmentez-le à cet endroit. Si cet appel reste lui aussi bloqué, le délai se situe dans Ollama. Les champs load_duration et prompt_eval_duration de la réponse indiquent si le modèle est en cours de chargement ou si Ollama lit votre prompt.

Pourquoi la première requête expire-t-elle alors que la suivante fonctionne ?

Ollama décharge un modèle inactif pour libérer de la mémoire, selon un délai défini par keep_alive. La valeur par défaut documentée est de 5 minutes, vérifiée en septembre 2026. La première requête après une période d’inactivité recharge le modèle depuis le disque et subit toute la durée du démarrage à froid. Une requête envoyée juste après trouve le modèle déjà chargé et répond rapidement. Exécutez ollama ps pour voir ce qui est chargé et quand le modèle expire. Définissez OLLAMA_KEEP_ALIVE=-1 pour le conserver en mémoire, en sachant que la mémoire restera occupée.

Pourquoi cela échoue-t-il uniquement lorsque je passe par nginx ?

nginx documente proxy_read_timeout avec une valeur par défaut de 60s. Ce délai s’applique entre deux lectures successives, et non à l’ensemble de la réponse. Une réponse en streaming réinitialise le délai à chaque bloc. En revanche, une requête envoyée avec "stream": false doit se terminer dans une seule fenêtre. C’est pourquoi la fenêtre de chat fonctionne alors qu’un script échoue. Recherchez upstream timed out (110: Connection timed out) while reading response header from upstream dans le journal d’erreurs nginx, puis augmentez proxy_read_timeout et définissez proxy_buffering off.

Augmenter OLLAMA_LOAD_TIMEOUT accélère-t-il le chargement ?

Non. Cela modifie uniquement la durée pendant laquelle le serveur attend avant d’abandonner et de journaliser timed out waiting for llama runner to start. Si le modèle ne tient pas en mémoire, la machine utilise le swap, le chargement devient très lent et un délai plus long ne fait que repousser l’échec sans le résoudre. Vérifiez la valeur par défaut de votre build en exécutant ollama --version et en consultant envconfig/config.go à ce tag. Considérez ensuite qu’un chargement qui nécessite plusieurs minutes indique qu’il faut utiliser une quantisation plus petite.