Ollama: solucionar "context deadline exceeded"
El error "context deadline exceeded" indica un tiempo agotado antes de responder. Identifica si lo fija el cliente, la carga del modelo o nginx y corrígelo.
Qué significa realmente "context deadline exceeded"
El error de Ollama context deadline exceeded indica un tiempo de espera agotado. Algún componente de 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 bloqueo 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, y eso 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).
Intervienen cinco capas. Tres establecen su propio plazo: el cliente, el tiempo de espera de carga del modelo del servidor y un reverse proxy. Las otras dos, keep_alive y num_ctx, no establecen ningún plazo, pero determinan cuánto trabajo debe completarse dentro de uno. Fallan en puntos diferentes y cada una requiere una solución distinta. Por tanto, el trabajo consiste en determinar cuál está detrás del error.
- El cliente HTTP, que asignó a la solicitud un presupuesto de tiempo fijo.
- El tiempo de espera de carga del modelo del servidor de Ollama, que se agota mientras un modelo grande se lee del disco por primera vez.
keep_alive, que descarga el modelo entre solicitudes, de modo que la siguiente llamada vuelve 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 reverse proxy como nginx o Traefik, que corta la conexión antes de que Ollama responda.
Siga la lista en ese orden. Cada paso siguiente elimina una capa del análisis, para que deje de trabajar a ciegas.
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.
Por qué la primera solicitud después de una pausa es 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 5 minutes, según la comprobación realizada en October 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 debe esperar todo el arranque en frío. La solicitud que agota el tiempo de espera es la primera después de un periodo de inactividad. Este es exactamente el patrón que suele describirse como aleatorio.
Compruebe qué está cargado en memoria ahora:
ollama ps
curl -s http://127.0.0.1:11434/api/psUna lista vacía o una expiración dentro de pocos 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. Establézcalo por solicitud o configure OLLAMA_KEEP_ALIVE en el servicio para aplicarlo a todas las solicitudes. El valor de la solicitud tiene prioridad: la documentación de Ollama indica que el parámetro de la API keep_alive sustituye al ajuste OLLAMA_KEEP_ALIVE. Por tanto, un cliente que envíe su propio keep_alive seguirá descargando el modelo según su propio intervalo.
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 preparar un servidor después de reiniciarlo. Debe incluirse en una unidad pequeña de systemd para que nadie tenga que esperar al primer arranque en frío después de un reinicio. El coste es claro: un modelo fijado mantiene su memoria ocupada indefinidamente. En un servidor pequeño puede fijar un modelo, no cuatro. Mantener un modelo residente entre solicitudes explica el cálculo de memoria y la unidad de preparación.
Por qué un num_ctx grande agota el tiempo de espera antes del primer token
Antes de generar cualquier contenido, 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 hace dos cosas a la vez. Limita cuántos tokens puede considerar el modelo y determina el tamaño de la caché KV (key value cache) que el servidor asigna de antemano. Ambas operaciones aumentan el trabajo.
En un servidor que sólo usa CPU, el prefill es lento y su duración aumenta de forma lineal con el número de tokens del prompt. Un documento largo pegado en un chat puede tardar minutos en la fase de prefill mientras el cliente no muestra nada, porque el streaming todavía no ha empezado. El cliente alcanza su tiempo límite e informa context deadline exceeded, mientras el servidor sigue trabajando. Compruébelo con los números de la sección anterior. Envíe el prompt largo y lea prompt_eval_count y prompt_eval_duration, que Ollama define como el tiempo dedicado a evaluar los tokens del prompt que no están en caché. Un valor de varios minutos ahí, junto con un eval_duration pequeño, indica que el tiempo se ha consumido en el prefill. Como sólo se cuentan los tokens que no están en caché, una repetición del mismo prompt en un modelo que todavía está cargado puede mostrar un valor mucho menor. Por eso, compare las primeras ejecuciones. Para ver el coste de una caché más grande, ejecute el prompt con "options": {"num_ctx": 2048} y después con 32768. Lea también load_duration, porque el tiempo dedicado a cargar el modelo se informa ahí y no en prompt_eval_duration.
El valor predeterminado del servidor procede de OLLAMA_CONTEXT_LENGTH, y un num_ctx por solicitud dentro del objeto options lo sustituye. Aumentarlo hasta el máximo anunciado por el modelo sólo porque ese máximo existe es el error habitual. La asignación de la caché KV puede expulsar el modelo de la RAM y convertir una configuración operativa en una configuración que usa swapping. 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 a la memoria.
Los datos de este gráfico
[
{
"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 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=-1y cárguelo durante el arranque para que las peticiones de los usuarios no asuman el coste de carga. Después, compruebe que ningún cliente envíe su propiokeep_alive, porque un valor incluido en la petición sustituye la configuración del servidor. - Reduzca
num_ctxa lo que realmente necesitan sus prompts. Esto acorta el prellenado y libera la memoria que retenía la caché KV. - Use 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 buffering para que los tokens transmitidos lleguen al cliente. - Aumente el tiempo de espera en su propio cliente, porque 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 peticiones simultáneas y pone las demás en cola. Por eso, un segundo cliente puede permanecer en la cola hasta que venza su propio plazo, aunque el modelo no sea lento. El registro del servidor muestra que la petición se atendió tarde, no que fallara. Qué ocurre cuando varias personas comparten un servidor Ollama explica la configuración del paralelismo, y la instalación base en un VPS explica la configuración del servicio que dan por supuestos estos ajustes.
FAQ
¿Qué significa "context deadline exceeded" en Ollama?
Significa que el plazo de la solicitud venció antes de que el modelo respondiera. La frase procede del paquete context de Go, por lo que la imprimió un programa de 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 algo esté roto o dañado. El siguiente paso es determinar qué capa estableció el plazo, porque el cliente, la carga del modelo y el proxy inverso establecen sus propios plazos, mientras que keep_alive y num_ctx determinan cuánto trabajo debe completarse dentro de ellos.
¿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, porque 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. Aumente el tiempo de espera en esa capa. Si esa llamada también se bloquea, el retraso está dentro de Ollama. 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é se agota el tiempo de espera de la primera solicitud y la siguiente funciona?
Ollama descarga un modelo inactivo para liberar memoria, según el intervalo establecido por keep_alive. El valor predeterminado documentado es de 5 minutos, comprobado en octubre de 2026. La primera solicitud después de un periodo de inactividad vuelve a cargar el modelo desde el disco y completa todo el arranque en frío. Una solicitud enviada justo después encuentra el modelo residente y responde rápidamente. Ejecute ollama ps para ver qué está cargado y cuándo caduca. Establezca OLLAMA_KEEP_ALIVE=-1 para mantener el modelo en memoria, teniendo en cuenta que la memoria seguirá ocupada. Un cliente que envía su propio keep_alive anula ese ajuste, así que compruebe también los clientes.
¿Por qué sólo falla cuando paso por nginx?
nginx documenta proxy_read_timeout con un valor predeterminado de 60s. Este tiempo de espera se aplica entre dos lecturas sucesivas, no a toda la respuesta. Una respuesta en streaming lo reinicia con cada bloque, mientras que una solicitud enviada con "stream": false debe completarse dentro de una única 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. Después, 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 rendirse 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 consultando envconfig/config.go en esa etiqueta. Considere que una carga que necesita minutos indica que debe elegir una cuantización más pequeña.