Ollama: cómo corregir context deadline exceeded
Si Ollama muestra exactamente "context deadline exceeded", identifica si el límite lo fija el cliente, la carga del modelo, keep_alive o nginx y aplica la corrección adecuada.
Qué significa realmente "context deadline exceeded"
El error de Ollama context deadline exceeded indica que se agotó un tiempo de espera. Alguna parte del código Go estableció un plazo para la solicitud, el modelo no terminó dentro de ese plazo y el plazo expiró. No se produjo ningún error grave ni se dañó ningún archivo. El trabajo seguía ejecutándose cuando se agotó el tiempo.
El texto procede del paquete estándar context de Go. Esto ya proporciona una pista útil. Un cliente de Python basado en httpx genera httpx.ReadTimeout en su lugar. Un navegador muestra un error de red genérico. Si está leyendo exactamente estas palabras, un programa Go dejó de esperar: la herramienta de línea de comandos de Ollama, el propio servidor de Ollama o una aplicación Go que llama a la API (interfaz de programación de aplicaciones).
Cinco capas pueden establecer ese plazo. Fallan en puntos diferentes y cada una requiere una corrección distinta. Por tanto, hay que determinar cuál se activó.
- El cliente HTTP, que asignó a la solicitud un tiempo máximo fijo.
- El tiempo de espera de carga del modelo del servidor de Ollama, que se activa cuando un modelo grande se lee del disco por primera vez.
keep_alive, que descarga el modelo entre solicitudes y hace que la siguiente llamada vuelva a asumir el coste de carga.- Un
num_ctxsuficientemente grande para que el procesamiento del prompt se prolongue durante minutos en un equipo que sólo usa la CPU. - Un proxy inverso como nginx o Traefik, que cierra la conexión antes de que Ollama responda.
Revise la lista en ese orden. Cada paso siguiente elimina una capa del análisis y evita que tenga que hacer suposiciones.
Reproduzca la solicitud directamente contra la API para descartar el proxy
Ejecute la solicitud en el propio servidor, directamente contra Ollama y sin ningún proxy intermedio.
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 400curl no establece por sí mismo un límite de tiempo total, sino sólo un tiempo de espera para la conexión. Por tanto, este comando espera todo el tiempo que Ollama necesite. Esto divide el problema en dos. Si devuelve un cuerpo JSON, Ollama respondió y el límite de tiempo pertenece a algún componente situado delante de él. Si esta llamada se queda bloqueada durante varios minutos, el retraso está dentro de Ollama y el proxy no es la causa.
Ahora envíe la misma solicitud a través de la URL pública y mida el tiempo.
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 estado 504 después de un número de segundos sospechosamente redondo, como 60.0 o 30.0, indica un tiempo de espera del proxy. Los proxies usan valores predeterminados redondos. Un modelo no termina exactamente en 60.000 segundos dos veces seguidas. Si la llamada directa se rechaza de inmediato en lugar de tardar, el problema está en el proceso que escucha y no en el límite de tiempo. qué dirección usa Ollama para escuchar en el puerto 11434 cubre ese caso.
Supervise el registro del servidor mientras se procesa la solicitud
Abra una segunda sesión y siga el registro del servicio. Después, vuelva a enviar la solicitud.
journalctl -u ollama --no-pager --follow --pager-endUn arranque en frío correcto registra la carga del modelo, después el inicio de un runner y, por último, la atención de la solicitud. Un error de carga se muestra de esta forma. Esta es la cadena que identifica el tiempo de espera de carga propio del servidor:
Error: timed out waiting for llama runner to start - progress 0.00 -Ese mensaje indica que el proceso del modelo no terminó de iniciarse dentro del tiempo asignado por el servidor. La cifra de progreso indica hasta dónde llegó. Un valor de 0.00 significa que el runner no informó de ningún progreso antes de alcanzar el plazo. Esto suele indicar que el archivo todavía se está leyendo o que la máquina está usando swap. Para obtener más información durante la carga, reinicie el servicio con OLLAMA_DEBUG=1 definido y repita la operación.
Medir si la demora corresponde a la carga o a la generación
Ollama informa de sus propios tiempos, por lo que no es necesario deducir esta parte.
ollama run --verbose llama3.1:8b "Why is the sky blue?"Después de la respuesta, muestra total duration, load duration, prompt eval count, prompt eval rate, eval count y eval rate. Ejecútelo dos veces. En la segunda ejecución, load duration debería reducirse casi a cero porque el modelo ya está residente. Si no se reduce, el modelo se descarga entre las dos ejecuciones. Este es el caso de keep_alive que se explica más adelante.
La API devuelve los mismos valores en el objeto JSON final, como load_duration, prompt_eval_duration y eval_duration. La documentación indica que todas las duraciones se devuelven en nanosegundos, por lo que debe dividirlas entre 10^9 para obtener los segundos.
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")})'Revise el valor más alto. Si load_duration es el valor dominante, tiene un problema con la carga del modelo. Vaya a las dos secciones siguientes. Si prompt_eval_duration es el valor dominante, el procesamiento del prompt es el coste principal. Vaya a la sección num_ctx. Si eval_duration es el valor dominante, el modelo simplemente genera texto lentamente en este hardware. Ningún ajuste de tiempo de espera cambiará ese comportamiento. Reduzca la longitud de la salida con num_predict o cambie a un modelo más pequeño.
Aumente OLLAMA_LOAD_TIMEOUT después de comprobar la versión
La variable del servidor que determina cuánto tiempo espera para iniciar un modelo es OLLAMA_LOAD_TIMEOUT. Su valor predeterminado ha cambiado entre versiones, así que consúltelo para su compilación y no en un artículo, incluido este. Muestre primero la versión.
ollama --versionDespués, abra el código fuente de esa etiqueta exacta, https://github.com/ollama/ollama/blob/<your version>/envconfig/config.go, y busque OLLAMA_LOAD_TIMEOUT. El valor de ese archivo es el valor predeterminado incluido en la compilación de su binario. Establezca su propio valor mediante un drop-in de systemd.
sudo systemctl edit ollama.serviceAñada las variables en una sección [Service]. Este es el método que proporciona la documentación de Ollama para Linux:
[Service]
Environment="OLLAMA_LOAD_TIMEOUT=15m"
Environment="OLLAMA_KEEP_ALIVE=-1"sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=EnvironmentEl último comando muestra el entorno que recibió realmente el servicio. Un resultado vacío significa que el drop-in se guardó fuera de los marcadores del editor o con un nombre de sección incorrecto, por lo que no se aplica nada de lo que configuró. Tenga claro qué consigue con esto: un tiempo de espera de carga más largo evita que el servidor abandone la operación, pero no acelera nada. Si el modelo no cabe en la memoria, la máquina usará swap, la carga será muy lenta y un valor mayor solo retrasará el fallo.
La primera solicitud después de una pausa es la lenta
Ollama descarga un modelo inactivo para liberar memoria. El ajuste keep_alive determina cuándo lo hace. La documentación de Ollama indica que el valor predeterminado es de 5 minutos, según la comprobación realizada en septiembre de 2026. Por tanto, una aplicación de chat que se usa una vez por hora vuelve a cargar el modelo con cada mensaje, y cada mensaje paga todo el tiempo de arranque en frío. La solicitud que agota el tiempo de espera es la primera después de un periodo de inactividad. Este patrón se describe precisamente como aleatorio.
Compruebe qué está cargado en memoria ahora mismo:
ollama ps
curl -s http://127.0.0.1:11434/api/psUna lista vacía o un vencimiento previsto para dentro de unos minutos lo confirma. keep_alive acepta una cadena de duración como "10m" o "24h", un número simple de segundos, 0 para descargar el modelo de inmediato y un número negativo para mantenerlo en memoria indefinidamente. Puede establecerlo por solicitud o configurar OLLAMA_KEEP_ALIVE en el servicio para aplicarlo a todas las solicitudes.
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"keep_alive": -1
}'Una solicitud con un modelo y sin prompt carga el modelo y termina. Esta es la forma documentada de calentar un sistema después de reiniciarlo. Debe incluirse en una unidad pequeña de systemd para que nadie tenga que esperar un arranque en frío. El coste es claro: un modelo fijado ocupa su memoria indefinidamente. Por tanto, en un sistema pequeño puede fijar un modelo, no cuatro. Mantener un modelo residente entre solicitudes explica el cálculo de memoria y la unidad de calentamiento.
Por qué un num_ctx grande agota el tiempo de espera antes del primer token
Antes de escribir nada, el modelo debe leer todo el prompt. Esta fase se denomina prefill y es lo que mide prompt eval. num_ctx establece la longitud del contexto y cumple dos funciones a la vez. Limita el número de tokens que el modelo puede considerar y determina el tamaño de la KV cache (key value cache) que el servidor asigna de antemano. Ambas cosas aumentan el trabajo.
En un servidor que sólo usa CPU, el prefill es lento y su duración crece de forma lineal con el número de tokens del prompt. Un documento largo pegado en un chat puede pasar varios minutos en prefill mientras el cliente no muestra nada, porque el streaming todavía no ha comenzado. El cliente alcanza su tiempo límite e informa de context deadline exceeded, mientras el servidor ha estado trabajando durante todo ese tiempo. Compruébelo con los valores de la sección anterior: ejecute el mismo prompt con "options": {"num_ctx": 2048} y después con 32768, y compare prompt_eval_duration.
El valor predeterminado del servidor procede de OLLAMA_CONTEXT_LENGTH, y un num_ctx por solicitud en el objeto options lo sobrescribe. Aumentarlo hasta el máximo anunciado por el modelo sólo porque ese máximo existe es el error habitual, ya que la asignación de la KV cache puede dejar al modelo sin RAM y convertir una configuración funcional en una configuración que usa swap. Cómo elegir num_ctx según la memoria disponible contiene los detalles del dimensionamiento.
Por qué nginx devuelve 504 Gateway Time-out
nginx documenta proxy_read_timeout con un valor predeterminado de 60s, y su registro de errores indica claramente el fallo:
upstream timed out (110: Connection timed out) while reading response header from upstreamEl detalle importante está en la documentación de nginx: el tiempo de espera «se establece sólo entre dos operaciones de lectura consecutivas, no para la transmisión de toda la respuesta». Una respuesta en streaming reinicia el contador con cada bloque, por lo que los chats en streaming siguen funcionando. Una solicitud con "stream": false no envía nada hasta que la respuesta está completa, por lo que toda la generación debe terminar dentro de esa única ventana. Por eso el mismo modelo funciona en la ventana de chat y agota el tiempo de espera cuando se usa desde 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 nginxproxy_buffering off es importante para el streaming. Con el almacenamiento en búfer activado, nginx puede recopilar la respuesta y entregarla al final, por lo que los tokens dejan de aparecer uno a uno y un stream que funciona empieza a parecer bloqueado.
Traefik aplica el mismo control en el ServersTransport que utiliza el router.
http:
serversTransports:
ollama:
forwardingTimeouts:
dialTimeout: "30s"
responseHeaderTimeout: "0s"
idleConnTimeout: "60s"responseHeaderTimeout cubre la espera de las cabeceras de respuesta después de escribir la solicitud, y cero significa que no hay tiempo de espera. El servicio debe hacer referencia al transport por su nombre mediante serversTransport: ollama; de lo contrario, ha editado un bloque que no utiliza nada.
Una cuantización más pequeña se carga más rápido porque hay menos datos que leer
La cuantización es la precisión con la que se almacenan los pesos. Una precisión menor produce un archivo más pequeño, y cargar un modelo consiste principalmente en leer ese archivo del disco en la memoria.
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
}
]Esos son los tamaños publicados en la página del modelo, no mediciones realizadas en un servidor de prueba. La compilación predeterminada de 8B ocupa 4.9 GB. La compilación de precisión completa del mismo modelo ocupa 16 GB: contiene más del triple de bytes que leer y requiere más del triple de memoria para almacenarse. En un servidor alquilado con almacenamiento compartido, esa diferencia puede determinar si la carga termina correctamente o si supera el tiempo de espera. Calcular qué modelo cabe en la RAM es la comprobación que debe realizar antes de descargar algo grande.
Qué cambiar en un servidor alquilado
Aplique estos cambios en el orden que indiquen las mediciones, de uno en uno, y vuelva a ejecutar el comando de medición después de cada cambio.
- Fije el modelo con
OLLAMA_KEEP_ALIVE=-1o cárguelo durante el arranque para que ninguna petición de usuario asuma el coste de carga. - Reduzca
num_ctxa lo que realmente necesitan sus prompts. Esto acorta el prefill y libera la memoria que ocupaba la caché KV. - Descargue una cuantización más pequeña para que la carga lea menos bytes y el modelo deje espacio para la caché.
- Aumente
proxy_read_timeouten nginx oresponseHeaderTimeouten Traefik y desactive el almacenamiento en búfer para que los tokens transmitidos lleguen al cliente. - Aumente el tiempo de espera en su propio cliente. Un programa en Go o Python con un límite de 30 segundos fallará ante cualquier modelo que tarde más en procesar la solicitud.
Hay otra causa que puede estar detrás de todas estas. Ollama atiende un número limitado de solicitudes simultáneas y pone en cola las demás. Por eso, un segundo cliente puede permanecer en la cola hasta que venza su propio plazo, aunque no haya ningún modelo lento. El registro del servidor muestra que la solicitud se atendió tarde, no que fallara. Qué ocurre cuando varias personas comparten un servidor de Ollama explica los ajustes de paralelismo, y la instalación base en un VPS explica la configuración del servicio que dan por supuestos estas sobrescrituras.
FAQ
¿Qué significa "context deadline exceeded" en Ollama?
Significa que el plazo de la solicitud expiró antes de que el modelo respondiera. La frase procede del paquete context de Go, por lo que la imprimió un programa escrito en Go: la herramienta de línea de comandos de Ollama, el servidor de Ollama o una aplicación de Go que llama a la API. Es un tiempo de espera agotado; no indica que haya nada roto o corrupto. El siguiente paso es determinar qué capa estableció el plazo, porque el cliente, la carga del modelo, keep_alive, num_ctx y el proxy inverso establecen sus propios plazos.
¿Debo aumentar el tiempo de espera del cliente o el de Ollama?
Mida primero. Envíe la solicitud con curl desde el propio servidor, directamente a http://127.0.0.1:11434, ya que curl no impone ningún límite de tiempo global. Si esa llamada devuelve un cuerpo JSON, Ollama está respondiendo y el plazo pertenece al cliente o al proxy; auméntelo allí. Si esa llamada también queda bloqueada, el retraso está dentro de Ollama, y los campos load_duration y prompt_eval_duration de la respuesta indican si el modelo se está cargando o si está leyendo la solicitud.
¿Por qué la primera solicitud agota el tiempo de espera y la siguiente funciona?
Ollama descarga de la memoria un modelo inactivo para liberar memoria, según el intervalo establecido por keep_alive. El valor predeterminado documentado es 5 minutos, comprobado en septiembre de 2026. La primera solicitud después de un periodo de inactividad vuelve a cargar el modelo desde el disco y soporta todo el arranque en frío, mientras que una solicitud enviada inmediatamente después lo encuentra residente y responde rápidamente. Ejecute ollama ps para ver qué está cargado y cuándo caduca. Establezca OLLAMA_KEEP_ALIVE=-1 para mantenerlo en memoria y acepte que la memoria permanecerá ocupada.
¿Por qué sólo falla cuando paso por nginx?
nginx documenta proxy_read_timeout con un valor predeterminado de 60s, y ese tiempo de espera se aplica entre dos lecturas consecutivas, no a toda la respuesta. Una respuesta en streaming lo reinicia con cada fragmento, mientras que una solicitud enviada con "stream": false debe completarse dentro de una sola ventana. Por eso la ventana de chat funciona y un script falla. Busque upstream timed out (110: Connection timed out) while reading response header from upstream en el registro de errores de nginx, aumente proxy_read_timeout y establezca proxy_buffering off.
¿Aumentar OLLAMA_LOAD_TIMEOUT acelera la carga?
No. Sólo cambia cuánto tiempo espera el servidor antes de abandonar y registrar timed out waiting for llama runner to start. Si el modelo no cabe en la memoria, la máquina usa swap, la carga avanza muy lentamente y un tiempo de espera mayor retrasa el fallo sin solucionarlo. Compruebe el valor predeterminado de su compilación ejecutando ollama --version y leyendo envconfig/config.go en esa etiqueta, y considere que una carga que necesita minutos indica que debe descargar una cuantización más pequeña.