Como corrigir context deadline exceeded no Ollama
Entenda o erro context deadline exceeded no Ollama e descubra se o timeout vem do cliente, do carregamento do modelo, do keep_alive ou do nginx.
O que “context deadline exceeded” realmente significa
O erro context deadline exceeded do Ollama é um relatório de timeout. Algum código Go definiu um prazo para o pedido, o modelo não terminou dentro desse prazo e o prazo expirou. Nada falhou e nenhum ficheiro está corrompido. O trabalho ainda estava em execução quando o tempo terminou.
A mensagem vem do pacote padrão context do Go. Isto já é uma pista útil. Um cliente Python baseado em httpx gera httpx.ReadTimeout. Um navegador mostra um erro de rede genérico. Se está a ler estas palavras exatas, um programa Go desistiu de esperar: a ferramenta de linha de comandos do Ollama, o próprio servidor Ollama ou uma aplicação Go que chama a API (interface de programação de aplicações).
Cinco camadas podem definir esse prazo. Elas falham em pontos diferentes e cada uma exige uma correção diferente. Portanto, o trabalho consiste em identificar qual delas foi acionada.
- O cliente HTTP, que atribuiu ao pedido um orçamento de tempo fixo.
- O timeout de carregamento do modelo do servidor Ollama, que é acionado quando um modelo grande é lido do disco pela primeira vez.
keep_alive, que descarrega o modelo entre pedidos para que a chamada seguinte volte a pagar o custo do carregamento.- Um
num_ctxsuficientemente grande para que o processamento do prompt, por si só, demore minutos numa máquina apenas com CPU. - Um reverse proxy, como nginx ou Traefik, que encerra a ligação antes de o Ollama responder.
Siga essa lista pela ordem apresentada. Cada passo abaixo elimina uma camada da análise, para que deixe de fazer suposições.
Reproduza a chamada diretamente na API para retirar o proxy da equação
Execute o pedido no próprio servidor, diretamente para o Ollama, sem nenhum proxy pelo caminho.
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 não define um limite de tempo total, apenas um tempo limite de ligação. Por isso, este comando aguarda o tempo que o Ollama precisar. Isto divide o problema em duas partes. Se for devolvido um corpo JSON, o Ollama respondeu e o limite pertence a algum componente à sua frente. Se esta chamada ficar bloqueada durante vários minutos, o atraso está dentro do Ollama e o proxy não é a causa.
Agora envie o mesmo pedido através do URL público e meça o tempo.
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}'Um estado 504 apresentado depois de um número de segundos suspeitosamente redondo, como 60.0 ou 30.0, indica um tempo limite do proxy. Os proxies usam valores predefinidos redondos. Um modelo não termina exatamente aos 60.000 segundos duas vezes seguidas. Se a chamada direta for recusada imediatamente, em vez de demorar, o problema está no listener e não no tempo limite. qual endereço o Ollama usa para escutar na porta 11434 explica esse caso.
Monitorize o log do servidor enquanto o pedido é processado
Abra uma segunda sessão e acompanhe o log do serviço. Depois, envie novamente o pedido.
journalctl -u ollama --no-pager --follow --pager-endUm arranque a frio normal regista o carregamento do modelo, depois o arranque de um runner e, por fim, o processamento do pedido. Um carregamento com falha aparece assim. Esta é a cadeia que identifica o timeout de carregamento definido pelo próprio servidor:
Error: timed out waiting for llama runner to start - progress 0.00 -Essa mensagem significa que o processo do modelo não terminou o arranque dentro do tempo atribuído pelo servidor. O valor de progresso indica até onde chegou. Um valor de 0.00 significa que o runner não comunicou qualquer progresso antes do prazo. Normalmente, isto indica que o ficheiro ainda está a ser lido ou que a máquina está a usar swap. Para obter mais detalhes durante o carregamento, reinicie o serviço com OLLAMA_DEBUG=1 definido e repita o procedimento.
Meça se o atraso vem do carregamento ou da geração
Ollama informa os próprios tempos, por isso não precisa de adivinhar esta parte.
ollama run --verbose llama3.1:8b "Why is the sky blue?"Depois da resposta, ele apresenta total duration, load duration, prompt eval count, prompt eval rate, eval count e eval rate. Execute o comando duas vezes. Na segunda execução, load duration deve diminuir para quase zero, porque o modelo já está residente. Se não diminuir, o modelo está a ser descarregado entre as duas execuções. Esse é o caso keep_alive descrito mais abaixo.
Os mesmos valores são devolvidos pela API no objeto JSON final, como load_duration, prompt_eval_duration e eval_duration. A documentação indica que todas as durações são devolvidas em nanossegundos. Divida por 10^9 para obter os 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")})'Leia o maior valor. Se load_duration dominar, existe um problema no carregamento do modelo. Avance para as duas secções seguintes. Se prompt_eval_duration dominar, o processamento do prompt é o custo principal. Avance para a secção num_ctx. Se eval_duration dominar, o modelo está simplesmente a gerar a resposta lentamente neste hardware. Nenhuma configuração de timeout vai alterar isso. Reduza o tamanho da saída com num_predict ou utilize um modelo menor.
Aumente OLLAMA_LOAD_TIMEOUT depois de verificar a versão
A variável do servidor que define durante quanto tempo ele aguarda o arranque de um modelo é OLLAMA_LOAD_TIMEOUT. O valor predefinido mudou entre versões. Por isso, consulte o valor correspondente à sua compilação, em vez de o obter de qualquer artigo, incluindo este. Primeiro, mostre a versão.
ollama --versionDepois, abra o código-fonte da tag exata, https://github.com/ollama/ollama/blob/<your version>/envconfig/config.go, e procure por OLLAMA_LOAD_TIMEOUT. O valor nesse ficheiro é o valor predefinido compilado no seu binário. Defina o seu próprio valor através de um drop-in do systemd.
sudo systemctl edit ollama.serviceAdicione as variáveis numa secção [Service]. Este é o método indicado pela própria documentação do 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=EnvironmentO último comando mostra o ambiente que o serviço recebeu efetivamente. Um resultado vazio significa que o drop-in foi guardado fora dos marcadores do editor ou numa secção com o nome errado. Nesse caso, nenhuma das definições está ativa. Tenha em conta o efeito desta alteração: um tempo limite de carregamento maior impede que o servidor desista, mas não torna o carregamento mais rápido. Se o modelo não couber na memória, a máquina usará swap, o carregamento ficará muito lento e um valor maior apenas adiará a falha.
Por que a primeira solicitação depois de uma pausa é lenta
Ollama descarrega um modelo ocioso para libertar memória. A configuração keep_alive define quando isso acontece. A documentação do Ollama indica o valor predefinido de 5 minutes, verificado em September 2026. Assim, uma aplicação de chat usada uma vez por hora recarrega o modelo em cada mensagem, e cada mensagem suporta todo o arranque a frio. A solicitação que excede o tempo limite é a primeira depois de um período sem atividade. Esse é exatamente o padrão descrito como aleatório.
Verifique o que está residente neste momento:
ollama ps
curl -s http://127.0.0.1:11434/api/psUma lista vazia ou uma expiração prevista para os próximos minutos confirma o comportamento. keep_alive aceita uma string de duração, como "10m" ou "24h", um número simples de segundos, 0 para descarregar imediatamente e um número negativo para manter o modelo na memória indefinidamente. Defina-o por solicitação ou defina OLLAMA_KEEP_ALIVE no serviço para todas as solicitações.
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"keep_alive": -1
}'Uma solicitação com um modelo e sem prompt carrega o modelo e termina. Essa é a forma documentada de aquecer um servidor depois de um reboot. Coloque-a numa pequena unidade systemd para que ninguém tenha de esperar por um arranque a frio. O custo é direto: um modelo mantido na memória ocupa essa memória indefinidamente. Por isso, num servidor pequeno, pode manter um modelo residente, não quatro. Manter um modelo residente entre solicitações explica os cálculos de memória e a unidade de aquecimento.
Por que um num_ctx elevado excede o tempo limite antes do primeiro token
Antes de escrever qualquer coisa, o modelo precisa de ler todo o prompt. Essa etapa é o prefill, e é isso que prompt eval mede. num_ctx define o tamanho do contexto e faz duas coisas ao mesmo tempo. Limita quantos tokens o modelo pode considerar e dimensiona a cache KV (key value cache) que o servidor aloca antecipadamente. Ambos aumentam o trabalho.
Num servidor apenas com CPU, o prefill é lento e cresce linearmente com o número de tokens do prompt. Um documento longo colado num chat pode passar minutos em prefill sem que o cliente veja qualquer resultado, porque o streaming ainda não começou. O cliente atinge o seu prazo e comunica context deadline exceeded, enquanto o servidor esteve a trabalhar durante todo esse tempo. Confirme isso com os números da secção anterior: execute o mesmo prompt com "options": {"num_ctx": 2048} e depois com 32768 e compare prompt_eval_duration.
O valor predefinido do servidor vem de OLLAMA_CONTEXT_LENGTH, e um num_ctx por pedido no objeto options substitui esse valor. Aumentá-lo até ao máximo anunciado pelo modelo apenas porque esse máximo existe é o erro habitual, pois a alocação da cache KV pode deixar o modelo sem RAM e transformar uma configuração funcional numa configuração com swapping. Escolher num_ctx com base na memória disponível contém os detalhes de dimensionamento.
Por que o nginx retorna 504 Gateway Time-out
O nginx documenta proxy_read_timeout com um valor predefinido de 60s, e o log de erros identifica claramente a falha:
upstream timed out (110: Connection timed out) while reading response header from upstreamO detalhe importante está na documentação do nginx: o timeout "é definido apenas entre duas operações de leitura consecutivas, não para a transmissão da resposta inteira". Uma resposta em streaming reinicia o contador a cada bloco, por isso os chats em streaming continuam a funcionar. Uma solicitação com "stream": false não envia nada até a resposta estar completa, portanto toda a geração precisa terminar dentro dessa janela. É por isso que o mesmo modelo funciona na janela de chat, mas expira quando é chamado por um 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 é importante para o streaming. Com o buffering ativado, o nginx pode acumular a resposta e entregá-la no final. Assim, os tokens deixam de aparecer um a um, e um stream funcional começa a parecer travado.
O Traefik aplica o mesmo controle no ServersTransport usado pelo router.
http:
serversTransports:
ollama:
forwardingTimeouts:
dialTimeout: "30s"
responseHeaderTimeout: "0s"
idleConnTimeout: "60s"responseHeaderTimeout cobre a espera pelos cabeçalhos da resposta depois que a solicitação é enviada, e zero significa que não há timeout. O serviço precisa referenciar o transport pelo nome com serversTransport: ollama. Caso contrário, você editou um bloco que não é usado.
Uma quantização menor carrega mais depressa porque há menos dados para ler
Quantização é a precisão com que os pesos são armazenados. Uma precisão menor significa um ficheiro menor, e carregar um modelo consiste principalmente em ler esse ficheiro do disco para a memória.
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
}
]Estes são os tamanhos publicados na página do modelo, não medições feitas num servidor de teste. A compilação 8B predefinida tem 4.9 GB. A compilação de precisão total do mesmo modelo tem 16 GB, mais de três vezes mais bytes para ler e mais de três vezes mais memória necessária para os manter. Num servidor alugado com armazenamento partilhado, essa diferença pode determinar se o carregamento termina ou excede o tempo limite. Determinar qual modelo cabe na sua RAM é a verificação a fazer antes de transferir algo grande.
O que alterar num servidor alugado
Aplique estas alterações pela ordem indicada pelas medições, uma de cada vez, e execute novamente o comando de medição depois de cada alteração.
- Fixe o modelo com
OLLAMA_KEEP_ALIVE=-1ou aqueça-o no arranque, para que nenhum pedido de utilizador tenha de suportar o custo do carregamento. - Reduza
num_ctxpara o valor de que os seus prompts realmente precisam. Isto encurta o prefill e liberta a memória que a cache KV estava a utilizar. - Carregue uma quantização menor, para que o carregamento leia menos bytes e o modelo deixe espaço para a cache.
- Aumente
proxy_read_timeoutno nginx ouresponseHeaderTimeoutno Traefik e desative o buffering, para que os tokens transmitidos cheguem ao cliente. - Aumente o timeout no seu próprio cliente, porque um programa Go ou Python com um limite de 30 segundos falhará perante qualquer modelo que demore mais tempo a processar.
Há outra causa por detrás de todas estas situações. O Ollama atende um número limitado de pedidos em simultâneo e coloca os restantes numa fila. Assim, um segundo cliente pode ficar na fila até o seu próprio prazo expirar, sem que exista qualquer modelo lento. O log do servidor mostra que o pedido foi atendido tarde, e não que falhou. O que acontece quando várias pessoas partilham o mesmo servidor Ollama explica as definições de paralelismo, e a instalação base numa VPS explica a configuração do serviço que estas substituições pressupõem.
FAQ
O que significa "context deadline exceeded" no Ollama?
Significa que o prazo limite do pedido expirou antes de o modelo responder. A expressão vem do pacote context do Go, por isso foi um programa Go que a apresentou: a ferramenta de linha de comandos do Ollama, o servidor Ollama ou uma aplicação Go que chama a API. É um timeout; nada está avariado nem corrompido. O passo seguinte é identificar qual camada definiu o prazo, porque o cliente, o carregamento do modelo, keep_alive, num_ctx e o reverse proxy definem os seus próprios prazos.
Devo aumentar o timeout do cliente ou o timeout do Ollama?
Meça primeiro. Envie o pedido com curl no próprio servidor, diretamente para http://127.0.0.1:11434, porque curl não impõe um limite de tempo global. Se essa chamada devolver um corpo JSON, o Ollama está a responder e o prazo pertence ao cliente ou ao proxy; aumente-o nessa camada. Se essa chamada também ficar bloqueada, o atraso está dentro do Ollama. Nesse caso, os campos load_duration e prompt_eval_duration da resposta indicam se o modelo está a ser carregado ou se está a ler o seu prompt.
Porque é que o primeiro pedido excede o tempo limite e o seguinte funciona?
O Ollama descarrega um modelo inativo para libertar memória, segundo um intervalo definido por keep_alive. O valor predefinido documentado é de 5 minutos, verificado em setembro de 2026. O primeiro pedido depois de um período de inatividade volta a carregar o modelo a partir do disco e suporta todo o arranque a frio. Um pedido enviado logo a seguir encontra o modelo residente e responde rapidamente. Execute ollama ps para ver o que está carregado e quando expira. Defina OLLAMA_KEEP_ALIVE=-1 para manter o modelo em memória e aceite que essa memória continuará ocupada.
Porque é que só falha quando passo pelo nginx?
O nginx documenta proxy_read_timeout com um valor predefinido de 60s. Esse timeout aplica-se entre duas leituras sucessivas, e não à resposta inteira. Uma resposta em streaming reinicia o timeout a cada bloco, enquanto um pedido enviado com "stream": false tem de terminar dentro de uma única janela. Por isso, a janela de chat funciona e um script falha. Procure upstream timed out (110: Connection timed out) while reading response header from upstream no log de erros do nginx. Depois, aumente proxy_read_timeout e defina proxy_buffering off.
Aumentar OLLAMA_LOAD_TIMEOUT torna o carregamento mais rápido?
Não. Apenas altera durante quanto tempo o servidor espera antes de desistir e registar timed out waiting for llama runner to start. Se o modelo não couber na memória, a máquina utiliza swap, o carregamento fica muito lento e um timeout maior apenas adia a falha, sem a corrigir. Verifique o valor predefinido da sua compilação executando ollama --version e lendo envconfig/config.go nessa tag. Considere um carregamento que demora vários minutos um sinal para obter uma quantização menor.