Ollama context deadline exceeded 오류 해결 방법
Ollama에서 발생하는 context deadline exceeded 오류의 원인을 분석합니다. 클라이언트 타임아웃, 모델 로드 시간, keep_alive 설정, 리버스 프록시 등 5가지 계층별 해결책을 제시하여 문제를 단계별로 진단하고 수정하는 방법을 안내합니다.
"context deadline exceeded"의 실제 의미
Ollama의 "context deadline exceeded" 오류는 타임아웃 보고입니다. Go 코드의 일부가 요청에 마감 기한을 설정했으나, 모델이 그 시간 내에 작업을 마치지 못해 기한이 만료된 것입니다. 프로그램이 충돌하거나 파일이 손상된 것은 아닙니다. 제한 시간이 지났을 때 작업은 여전히 실행 중이었습니다.
이 문구는 Go 표준 context 패키지에서 유래했으며, 그 자체로 유용한 단서가 됩니다. httpx 기반의 Python 클라이언트는 대신 httpx.ReadTimeout 예외를 발생시킵니다. 브라우저는 단순한 네트워크 오류를 표시합니다. 이 정확한 문구를 보고 있다면, Ollama 명령줄 도구, Ollama 서버 자체, 또는 API(application programming interface)를 호출하는 Go 애플리케이션 중 하나가 대기를 포기한 것입니다.
다섯 가지 계층에서 해당 마감 기한을 설정할 수 있습니다. 각 계층은 서로 다른 지점에서 실패하며 해결 방법도 다르므로, 어떤 계층에서 타임아웃이 발생했는지 파악하는 것이 전체 작업의 핵심입니다.
- 요청에 고정된 시간 예산을 할당한 HTTP 클라이언트.
- 대규모 모델을 디스크에서 처음 읽어올 때 발생하는 Ollama 서버의 모델 로드 타임아웃.
- 요청 사이에 모델을 언로드하여 다음 호출 시 로드 비용을 다시 발생시키는
keep_alive. - CPU 전용 장비에서 프롬프트 처리만으로 수 분이 소요될 정도로 큰
num_ctx. - Ollama가 응답하기 전에 연결을 끊어버리는 nginx나 Traefik 같은 리버스 프록시.
위 목록을 순서대로 확인하십시오. 아래의 각 단계는 문제의 원인이 되는 계층을 하나씩 제거하므로, 추측을 멈추고 원인을 찾을 수 있습니다.
프록시를 제외하고 API에 직접 요청하여 재현하기
프록시를 거치지 않고 서버에서 Ollama로 직접 요청을 보냅니다.
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는 자체적인 전체 시간 제한을 두지 않고 연결 제한 시간만 설정하므로, 이 명령은 Ollama가 응답할 때까지 대기합니다. 이를 통해 문제의 원인을 절반으로 좁힐 수 있습니다. JSON 본문이 반환된다면 Ollama는 정상적으로 응답한 것이며, 제한 시간 문제는 프록시 설정에 있는 것입니다. 만약 이 호출 자체가 몇 분 동안 응답이 없다면 지연의 원인은 Ollama 내부에 있으며 프록시는 무관합니다.
이제 동일한 요청을 공용 URL을 통해 보내고 소요 시간을 측정합니다.
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}'60.0초나 30.0초와 같이 의심스러울 정도로 딱 떨어지는 시간에 504 상태가 출력된다면 이는 프록시의 시간 제한 때문입니다. 프록시는 기본값으로 정수 단위를 사용합니다. 모델이 두 번 연속으로 정확히 60.000초 만에 작업을 마칠 수는 없습니다. 직접 호출했을 때 느린 것이 아니라 즉시 거부된다면 이는 제한 시간 문제가 아니라 리스너 문제입니다. 이 경우 Ollama가 11434 포트에서 바인딩하는 주소 항목을 확인하십시오.
요청이 실행되는 동안 서버 로그 모니터링
두 번째 세션을 열어 서비스 로그를 팔로우한 다음, 요청을 다시 보냅니다.
journalctl -u ollama --no-pager --follow --pager-end정상적인 콜드 스타트라면 모델이 로드되고, 러너가 시작된 뒤, 요청이 처리되는 과정이 로그에 남습니다. 로드에 실패하면 대신 다음과 같은 메시지가 나타나며, 이 문자열을 통해 서버 자체의 로드 타임아웃 여부를 식별할 수 있습니다.
Error: timed out waiting for llama runner to start - progress 0.00 -해당 메시지는 서버에 할당된 시간 내에 모델 프로세스가 시작을 완료하지 못했음을 의미합니다. 진행률 수치는 프로세스가 어디까지 진행되었는지를 나타냅니다. 0.00라는 값은 기한 내에 러너로부터 아무런 응답을 받지 못했음을 의미하며, 이는 보통 파일을 읽는 중이거나 시스템에서 스왑이 발생하고 있음을 뜻합니다. 로드 과정에 대한 자세한 정보를 확인하려면 OLLAMA_DEBUG=1를 설정한 상태로 서비스를 재시작한 뒤 다시 시도하십시오.
지연 시간이 로딩 때문인지 생성 때문인지 측정하기
Ollama는 자체적인 타이밍 정보를 제공하므로 이 부분을 추측할 필요가 없습니다.
ollama run --verbose llama3.1:8b "Why is the sky blue?"답변이 출력된 후 total duration, load duration, prompt eval count, prompt eval rate, eval count 및 eval rate이 표시됩니다. 이 명령을 두 번 실행하십시오. 두 번째 실행 시에는 모델이 이미 메모리에 상주하고 있으므로 load duration 값이 거의 0에 가깝게 떨어져야 합니다. 만약 값이 떨어지지 않는다면 두 실행 사이에 모델이 메모리에서 해제되고 있는 것이며, 이는 아래에서 다룰 keep_alive 사례에 해당합니다.
동일한 수치들이 API의 최종 JSON 객체 내 load_duration, prompt_eval_duration 및 eval_duration으로 반환됩니다. 문서에 따르면 모든 지속 시간은 나노초 단위로 반환되므로, 10^9로 나누어 초 단위로 확인하십시오.
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")})'가장 큰 수치를 확인하십시오. load_duration이 지배적이라면 모델 로딩에 문제가 있는 것이므로 다음 두 섹션으로 이동하십시오. prompt_eval_duration이 지배적이라면 프롬프트 처리 비용이 문제이므로 num_ctx 섹션으로 이동하십시오. eval_duration이 지배적이라면 현재 하드웨어에서 모델 생성 속도가 단순히 느린 것이며, 타임아웃 설정 변경으로는 해결할 수 없습니다. num_predict을 사용하여 출력 길이를 줄이거나 더 작은 모델로 변경하십시오.
OLLAMA_LOAD_TIMEOUT 값 상향 조정 및 버전 확인
모델이 시작될 때까지 대기하는 시간을 결정하는 서버 변수는 OLLAMA_LOAD_TIMEOUT입니다. 이 값의 기본 설정은 릴리스마다 변경되므로, 본 문서를 포함한 외부 자료를 참고하기보다 현재 설치된 빌드 버전을 직접 확인해야 합니다. 먼저 버전을 출력하십시오.
ollama --version그런 다음 해당 태그의 소스 코드인 https://github.com/ollama/ollama/blob/<your version>/envconfig/config.go을 열고 OLLAMA_LOAD_TIMEOUT를 검색하십시오. 해당 파일에 명시된 값이 바이너리에 컴파일된 기본값입니다. systemd drop-in 파일을 사용하여 직접 값을 설정하십시오.
sudo systemctl edit ollama.serviceOllama 공식 문서에서 Linux 환경을 위해 권장하는 방식에 따라 [Service] 섹션 아래에 변수를 추가하십시오.
[Service]
Environment="OLLAMA_LOAD_TIMEOUT=15m"
Environment="OLLAMA_KEEP_ALIVE=-1"sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment마지막 명령은 서비스가 실제로 전달받은 환경 변수를 출력합니다. 결과가 비어 있다면 drop-in 파일이 편집기 마커 밖에 저장되었거나 잘못된 섹션 이름 아래에 작성된 것이므로, 설정한 값이 적용되지 않은 상태입니다. 이 설정의 목적을 명확히 이해해야 합니다. 로드 타임아웃을 늘리는 것은 서버가 작업을 포기하지 않게 할 뿐, 처리 속도를 높여주지는 않습니다. 모델이 메모리에 적재되지 않으면 시스템은 스왑을 사용하게 되고 로드 속도는 매우 느려지며, 값을 크게 설정하는 것은 단지 실패 시점을 뒤로 미룰 뿐입니다.
일시 정지 후 첫 번째 요청이 느린 이유
Ollama는 메모리를 확보하기 위해 유휴 상태인 모델을 메모리에서 해제합니다. keep_alive 설정이 그 시점을 결정합니다. 2026년 9월 확인된 Ollama 문서에 따르면 기본값은 5분입니다. 따라서 한 시간에 한 번 사용하는 채팅 앱은 메시지를 보낼 때마다 모델을 다시 로드하게 되며, 모든 메시지마다 전체 콜드 스타트 비용을 지불하게 됩니다. 타임아웃이 발생하는 요청은 정적 상태가 지난 후의 첫 번째 요청이며, 이는 사용자들이 무작위로 발생한다고 설명하는 현상과 정확히 일치합니다.
현재 메모리에 상주 중인 모델을 확인하십시오:
ollama ps
curl -s http://127.0.0.1:11434/api/ps목록이 비어 있거나 만료 시간이 몇 분 남지 않았다면 이를 뒷받침합니다. keep_alive은 "10m" 또는 "24h"와 같은 지속 시간 문자열, 단순 초 단위 숫자, 즉시 해제하기 위한 0, 그리고 모델을 메모리에 무기한 유지하기 위한 음수를 인자로 받습니다. 요청별로 설정하거나, 모든 요청에 대해 서비스 수준에서 OLLAMA_KEEP_ALIVE을 설정할 수 있습니다.
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"keep_alive": -1
}'모델은 포함하되 프롬프트는 없는 요청을 보내면 모델이 로드된 후 반환됩니다. 이는 재부팅 후 서버를 예열하는 문서화된 방법이며, 사용자가 콜드 스타트를 기다리지 않도록 작은 systemd 유닛에 포함하는 것이 좋습니다. 비용은 명확합니다. 고정된 모델은 메모리를 계속 점유하므로, 작은 서버에서는 4개가 아닌 1개의 모델만 고정할 수 있습니다. 요청 간 모델 상주 유지에서 메모리 계산 방식과 예열 유닛에 대해 자세히 다룹니다.
num_ctx 값이 클 때 첫 토큰 생성 전 타임아웃이 발생하는 이유
모델이 내용을 작성하기 전에 전체 프롬프트를 읽어야 합니다. 이 단계를 프리필(prefill)이라고 하며, prompt eval가 이를 측정합니다. num_ctx은 컨텍스트 길이를 설정하며, 이 설정은 두 가지 작업을 동시에 수행합니다. 모델이 고려할 수 있는 토큰 수를 제한하고, 서버가 미리 할당하는 KV 캐시(key value cache)의 크기를 결정합니다. 두 작업 모두 처리 부하를 증가시킵니다.
CPU 전용 서버에서 프리필은 느리며, 프롬프트 토큰 수에 비례하여 시간이 소요됩니다. 채팅창에 긴 문서를 붙여넣으면 스트리밍이 시작되지 않았기 때문에 클라이언트는 아무것도 보지 못한 채 프리필 단계에서 수 분을 대기할 수 있습니다. 클라이언트는 제한 시간을 초과하여 컨텍스트 마감 기한 초과(context deadline exceeded) 오류를 보고하지만, 서버는 그동안 계속 작업을 수행하고 있는 상태입니다. 이전 섹션의 수치로 이를 증명해 보십시오. "options": {"num_ctx": 2048}를 사용한 프롬프트와 32768를 사용한 프롬프트를 각각 실행하여 prompt_eval_duration을 비교하십시오.
서버 기본값은 OLLAMA_CONTEXT_LENGTH에서 결정되며, options 객체 내의 요청별 num_ctx 설정이 이를 덮어씁니다. 모델의 최대 허용치가 존재한다고 해서 무조건 그 값으로 높이는 것은 흔한 실수입니다. KV 캐시 할당으로 인해 모델이 RAM에서 밀려나면 정상 작동하던 설정이 스왑(swapping)을 유발하는 상태로 변할 수 있기 때문입니다. 실제 메모리에 따른 num_ctx 선택하기에서 크기 산정 세부 정보를 확인하십시오.
Nginx가 504 Gateway Time-out을 반환하는 이유
Nginx 문서는 proxy_read_timeout을 기본값 60s으로 정의하며, 에러 로그는 해당 실패 원인을 명확하게 기록합니다.
upstream timed out (110: Connection timed out) while reading response header from upstream중요한 세부 사항은 Nginx 문서에 명시되어 있습니다. 이 타임아웃은 "전체 응답 전송 시간이 아니라, 연속된 두 읽기 작업 사이의 시간"으로 설정됩니다. 스트리밍 응답은 데이터 조각(chunk)이 전송될 때마다 타이머를 초기화하므로 스트리밍 채팅은 타임아웃 없이 유지됩니다. 반면 "stream": false를 사용하는 요청은 답변이 완료될 때까지 아무것도 보내지 않으므로, 전체 생성 과정이 해당 시간 내에 종료되어야 합니다. 이것이 동일한 모델이 채팅창에서는 작동하지만 스크립트에서는 타임아웃이 발생하는 이유입니다.
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은 스트리밍에서 중요한 역할을 합니다. 버퍼링이 활성화된 상태에서 Nginx는 응답을 모두 모은 뒤 한꺼번에 전달할 수 있습니다. 이 경우 토큰이 하나씩 나타나지 않고, 정상적인 스트림이 마치 멈춘 것처럼 보일 수 있습니다.
Traefik은 라우터가 사용하는 ServersTransport에서 동일한 제어를 수행합니다.
http:
serversTransports:
ollama:
forwardingTimeouts:
dialTimeout: "30s"
responseHeaderTimeout: "0s"
idleConnTimeout: "60s"responseHeaderTimeout는 요청이 작성된 후 응답 헤더를 기다리는 시간을 제어하며, 0으로 설정하면 타임아웃이 비활성화됩니다. 서비스는 serversTransport: ollama를 사용하여 해당 트랜스포트를 이름으로 참조해야 합니다. 그렇지 않으면 아무것도 사용하지 않는 블록을 편집한 셈이 됩니다.
더 작은 양자화 모델은 읽어야 할 데이터가 적어 더 빠르게 로드됩니다
양자화는 가중치를 저장하는 정밀도를 의미합니다. 정밀도가 낮을수록 파일 크기가 작아지며, 모델 로딩은 대부분 디스크에서 메모리로 파일을 읽어오는 과정입니다.
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
}
]위 수치는 모델 페이지에 게시된 크기이며, 테스트 환경에서 직접 측정한 결과가 아닙니다. 기본 8B 빌드의 배포 크기는 4.9 GB입니다. 동일 모델의 전체 정밀도 빌드는 16 GB로, 읽어야 할 데이터 양이 3배 이상 많고 메모리 점유량도 3배 이상 큽니다. 공유 스토리지를 사용하는 임대 서버에서는 이 차이가 로딩 성공과 타임아웃 발생을 가르는 결정적인 요인이 됩니다. 대용량 모델을 내려받기 전에 사용 가능한 RAM에 맞는 모델 확인하기를 먼저 수행해야 합니다.
임대 서버에서 변경해야 할 사항
다음 항목들을 측정 결과가 가리키는 순서대로 하나씩 적용하고, 적용할 때마다 타이밍 명령을 다시 실행하십시오.
OLLAMA_KEEP_ALIVE=-1을 사용하여 모델을 고정하거나 부팅 시점에 미리 로드하여, 사용자 요청이 로드 비용을 부담하지 않도록 하십시오.num_ctx을 실제 프롬프트에 필요한 수준으로 낮추십시오. 이렇게 하면 프리필(prefill) 시간이 단축되고 KV 캐시가 점유하던 메모리가 확보됩니다.- 더 작은 양자화 모델을 가져오십시오. 로드 시 읽는 바이트 수가 줄어들며 모델이 캐시를 위한 공간을 확보하게 됩니다.
- Nginx의
proxy_read_timeout또는 Traefik의responseHeaderTimeout를 높이고, 버퍼링을 꺼서 스트리밍되는 토큰이 클라이언트에 즉시 도달하도록 하십시오. - 클라이언트의 타임아웃 설정을 높이십시오. 30초 제한을 둔 Go나 Python 프로그램은 그보다 오래 생각하는 모델을 만나면 실패하게 됩니다.
이 모든 문제 뒤에는 또 다른 원인이 숨어 있습니다. Ollama는 한 번에 제한된 수의 요청만 처리하고 나머지는 대기열에 넣습니다. 따라서 두 번째 호출자는 모델이 느리지 않더라도 자신의 제한 시간이 만료될 때까지 대기열에서 기다릴 수 있습니다. 서버 로그에는 요청이 실패한 것이 아니라 늦게 처리된 것으로 나타납니다. 여러 사용자가 하나의 Ollama 서버를 공유할 때 발생하는 현상에서 병렬 처리 설정을 다루며, VPS 기본 설치에서 이러한 오버라이드가 전제로 하는 서비스 설정을 다룹니다.
FAQ
Ollama에서 "context deadline exceeded"는 무엇을 의미합니까?
모델이 응답하기 전에 요청에 설정된 기한이 만료되었다는 뜻입니다. 이 문구는 Go의 context 패키지에서 유래했으며, Ollama 명령줄 도구, Ollama 서버 또는 API를 호출하는 Go 애플리케이션 등 Go 프로그램이 출력한 것입니다. 이는 타임아웃 오류이므로 시스템이 손상되거나 깨진 것은 아닙니다. 클라이언트, 모델 로드, keep_alive, num_ctx 및 리버스 프록시가 각각 고유한 기한을 설정하므로, 어느 계층에서 기한을 설정했는지 확인하는 것이 다음 단계입니다.
클라이언트 타임아웃을 높여야 합니까, 아니면 Ollama의 타임아웃을 높여야 합니까?
먼저 측정하십시오. curl는 전체 시간 제한을 두지 않으므로, 서버 자체에서 curl을 사용하여 http://127.0.0.1:11434로 직접 요청을 보내십시오. 해당 호출이 JSON 본문을 반환한다면 Ollama는 정상적으로 응답하고 있는 것이며, 기한 설정은 클라이언트나 프록시에 있으므로 해당 설정값을 높여야 합니다. 만약 그 호출조차 응답이 없다면 지연은 Ollama 내부에서 발생하는 것이며, 응답의 load_duration 및 prompt_eval_duration 필드를 통해 모델이 로드 중인지 아니면 프롬프트를 읽는 중인지 확인할 수 있습니다.
왜 첫 번째 요청은 타임아웃이 발생하고 다음 요청은 정상적으로 작동합니까?
Ollama는 keep_alive에 설정된 일정에 따라 메모리를 확보하기 위해 유휴 상태인 모델을 언로드합니다. 2026년 9월 기준으로 문서화된 기본값은 5분입니다. 유휴 기간 이후의 첫 번째 요청은 디스크에서 모델을 다시 로드하므로 전체 콜드 스타트 시간이 소요되지만, 바로 이어서 보내는 요청은 모델이 메모리에 상주하므로 빠르게 반환됩니다. 무엇이 로드되어 있고 언제 만료되는지 확인하려면 ollama ps를 실행하십시오. 모델을 메모리에 계속 유지하려면 OLLAMA_KEEP_ALIVE=-1을 설정하되, 메모리가 계속 점유된다는 점을 감수해야 합니다.
왜 nginx를 거칠 때만 실패합니까?
nginx는 60s를 기본값으로 하는 proxy_read_timeout을 문서화하고 있으며, 이 타임아웃은 전체 응답이 아닌 연속된 두 읽기 작업 사이의 시간에 적용됩니다. 스트리밍 응답은 청크가 전달될 때마다 이 시간을 초기화하지만, "stream": false으로 보낸 요청은 단일 윈도우 내에 완료되어야 합니다. 이것이 채팅 창은 작동하는데 스크립트는 실패하는 이유입니다. nginx 오류 로그에서 upstream timed out (110: Connection timed out) while reading response header from upstream를 찾은 다음, proxy_read_timeout를 높이고 proxy_buffering off을 설정하십시오.
OLLAMA_LOAD_TIMEOUT을 높이면 로딩이 더 빨라집니까?
아니요. 이는 서버가 포기하고 timed out waiting for llama runner to start을 기록하기 전까지 기다리는 시간만 변경할 뿐입니다. 모델이 메모리에 맞지 않아 시스템이 스왑을 사용하게 되면 로딩 속도가 매우 느려지며, 타임아웃을 늘리는 것은 문제를 해결하지 못한 채 실패 시점만 뒤로 미루는 결과가 됩니다. 해당 태그의 envconfig/config.go를 읽고 ollama --version을 실행하여 빌드의 기본값을 확인하십시오. 로드에 수 분이 걸린다면 더 작은 양자화 모델을 가져오는 것을 고려해야 합니다.