Ollamaのcontext deadline exceededを解決する方法
Ollamaのエラー「context deadline exceeded」は応答前のタイムアウトです。クライアント、モデル読み込み、keep_alive、CPU処理、nginxのどこで期限が切れたか特定して直します。
「context deadline exceeded」が実際に意味すること
Ollama のエラー context deadline exceeded は、タイムアウトを示します。Go コードのどこかでリクエストに期限が設定され、モデルがその期限内に処理を完了できず、期限が切れました。クラッシュが発生したわけでも、ファイルが破損したわけでもありません。期限が切れた時点では、処理はまだ実行中でした。
この文言は、Go の標準 context パッケージに由来します。これだけでも有用な手掛かりになります。httpx を基盤にした Python クライアントは、代わりに httpx.ReadTimeout を発生させます。ブラウザーでは、単純なネットワークエラーとして表示されます。この正確な文言が表示されている場合、Go プログラムが待機を中断しています。対象は Ollama のコマンドラインツール、Ollama サーバー自体、または API(application programming interface)を呼び出す Go アプリケーションです。
この期限は、5 つの層で設定される可能性があります。各層は異なる時点で失敗し、必要な対処も異なります。そのため、どの層が期限を発生させたのかを特定する必要があります。
- リクエストに固定の時間制限を設定した HTTP クライアント。
- Ollama サーバーのモデル読み込みタイムアウト。大きなモデルを初回にディスクから読み込んでいる間に発生します。
keep_alive。リクエスト間でモデルをアンロードするため、次の呼び出しで再び読み込み時間がかかります。num_ctx。CPU のみの環境では、プロンプト処理だけで数分かかるほど大きな値です。- nginx や Traefik などのリバースプロキシ。Ollama が応答する前に接続を切断します。
このリストを上から順に確認してください。以下の各手順では、原因候補を 1 つずつ切り離します。推測だけで判断せずに済みます。
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 秒ちょうどで 2 回続けて処理を完了することはありません。直接呼び出すと遅いのではなく即座に拒否される場合、問題は制限時間ではなくリスナーにあります。このケースについては、Ollama が port 11434 でバインドするアドレスを参照してください。
サーバーログをリクエストの実行中に監視する
2 つ目のセッションを開き、サービスのログを追跡します。その後、リクエストをもう一度送信します。
journalctl -u ollama --no-pager --follow --pager-end正常なコールドスタートでは、モデルの読み込み、runner の起動、リクエストの処理の順にログが記録されます。読み込みに失敗した場合は、代わりに次のように表示されます。この文字列が、サーバー独自の読み込みタイムアウトを示します。
Error: timed out waiting for llama runner to start - progress 0.00 -このメッセージは、サーバーに割り当てられた時間内にモデルプロセスの起動が完了しなかったことを示します。進捗値から、処理がどこまで進んだかを確認できます。0.00 は、期限までに runner から何も報告されなかったことを意味します。通常は、ファイルの読み込み中か、マシンでスワップが発生しています。読み込み中の詳細を確認するには、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 が出力されます。2 回実行してください。2 回目はモデルがすでにメモリ上に常駐しているため、load duration がほぼゼロまで減るはずです。減らない場合は、2 回の実行の間にモデルがアンロードされています。これは後述する keep_alive のケースです。
同じ数値は、最終的な JSON オブジェクト内の load_duration、prompt_eval_duration、eval_duration として API からも返されます。ドキュメントによると、すべての処理時間はナノ秒単位で返されます。秒単位で読むには、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 が大きい場合は、モデルの読み込みに問題があります。次の 2 つのセクションに進んでください。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.service[Service] セクションの下に変数を追加します。これは、Ollama の公式ドキュメントが 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最後のコマンドは、サービスが実際に受け取った環境変数を表示します。結果が空の場合、drop-in がエディターのマーカー外に保存されたか、セクション名が間違っているため、設定が有効になっていません。この設定で得られる効果を明確にしておきます。ロードタイムアウトを延長すると、サーバーが待機を打ち切らなくなりますが、処理が速くなるわけではありません。モデルがメモリに収まらない場合、マシンは swap を使用し、ロードは大幅に遅くなります。値を大きくしても、失敗する時点が後ろにずれるだけです。
一時停止後に最初のリクエストだけ遅い理由
Ollama は、メモリを解放するため、アイドル状態のモデルをアンロードします。keep_alive 設定でアンロードするタイミングを指定します。Ollama のドキュメントでは、2026 年 9 月時点のデフォルト値は 5 分です。そのため、1 時間に 1 回だけ使用するチャットアプリでは、メッセージを送るたびにモデルが再読み込みされ、毎回コールドスタートの時間が発生します。タイムアウトするリクエストは、静止時間の後に送られた最初のリクエストです。これは、「ランダムに発生する」と説明される現象と一致します。
現在メモリ上に保持されているモデルを確認します。
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 unit に組み込んでください。代わりに、固定したモデルはメモリを無期限に保持します。小規模なマシンでは、4 つではなく 1 つのモデルだけを固定できます。リクエスト間でモデルをメモリに保持する方法では、メモリ使用量の計算とウォームアップ用 unit について説明します。
大きな num_ctx で最初のトークンより前にタイムアウトする理由
モデルは何かを書き始める前に、プロンプト全体を読み取る必要があります。この段階が prefill であり、prompt eval が測定する処理です。num_ctx はコンテキスト長を設定します。これにより、モデルが考慮できるトークン数の上限と、サーバーが事前に確保する KV cache(key value cache)の容量が同時に決まります。どちらも処理量を増加させます。
CPU のみのサーバーでは prefill が遅く、プロンプトのトークン数に対して線形に増加します。チャットに長い文書を貼り付けると、ストリーミングがまだ開始されないため、クライアントには何も表示されないまま prefill に数分かかることがあります。クライアントは期限に達して context deadline exceeded を報告しますが、その間もサーバーは処理を続けています。前のセクションの数値で確認できます。同じプロンプトを "options": {"num_ctx": 2048} と 32768 で実行し、prompt_eval_duration を比較してください。
サーバーのデフォルト値は OLLAMA_CONTEXT_LENGTH から取得されます。options オブジェクト内のリクエスト単位の num_ctx を指定すると、デフォルト値が上書きされます。最大値が存在するという理由だけで、モデルが公表している最大値まで引き上げるのは、よくある誤りです。KV cache の確保によってモデルが RAM に収まらなくなり、正常に動作していた構成が swap を使用する構成に変わる可能性があるためです。サイズの決め方については、実際のメモリ容量に基づく num_ctx の選び方を参照してください。
nginx が 504 Gateway Time-out を返す理由
nginx の proxy_read_timeout のデフォルト値は 60s です。エラーログには失敗の理由が明確に記録されます。
upstream timed out (110: Connection timed out) while reading response header from upstreamnginx のドキュメントで重要なのは、このタイムアウトが「レスポンス全体の送信ではなく、連続する 2 回の読み取り操作の間だけ設定される」という点です。ストリーミングレスポンスではチャンクを受信するたびにタイマーがリセットされるため、ストリーミングチャットは処理を継続できます。"stream": false を指定したリクエストは、回答が完成するまで何も送信しません。そのため、生成全体をこの 1 回の待機時間内に完了させる必要があります。同じモデルがチャット画面では動作し、スクリプトからはタイムアウトするのはこのためです。
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 が重要です。バッファリングを有効にすると、nginx がレスポンスを収集して最後にまとめて渡すため、トークンが 1 つずつ表示されなくなります。その結果、正常に動作しているストリームがハングしたように見えます。
Traefik では、ルーターが使用する ServersTransport に同じ設定を指定します。
http:
serversTransports:
ollama:
forwardingTimeouts:
dialTimeout: "30s"
responseHeaderTimeout: "0s"
idleConnTimeout: "60s"responseHeaderTimeout は、リクエストの書き込み後にレスポンスヘッダーを待つ時間を指定します。0 はタイムアウトなしを意味します。サービスでは serversTransport: ollama を使って transport を名前で参照する必要があります。そうしないと、使用されていない設定ブロックを編集しただけになります。
量子化が小さいほど、読み込むデータ量が少ないため高速にロードできます
量子化とは、重みを保存する精度です。精度を下げるとファイルが小さくなります。モデルのロードでは、通常、そのファイルをディスクからメモリへ読み込む処理が大半を占めます。
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 倍を超えます。共有ストレージを使用するレンタルサーバーでは、この差によってロードが完了するか、タイムアウトするかが決まります。大きなモデルを取得する前に、使用する RAM に適合するモデルの確認を実行してください。
レンタルサーバーで変更する項目
計測結果が示す順番に、これらを 1 つずつ適用します。各変更後にタイミング用コマンドを再実行します。
OLLAMA_KEEP_ALIVE=-1でモデルを固定するか、起動時にモデルをウォームアップします。これにより、ユーザーのリクエストでロード時間が発生しません。num_ctxを、実際にプロンプトで必要な値まで下げます。これにより prefill が短くなり、KV cache が使用していたメモリを解放できます。- より小さい量子化モデルを使用します。ロード時に読み取るバイト数が減り、モデルが cache 用の領域を確保できます。
- nginx の
proxy_read_timeoutまたは Traefik のresponseHeaderTimeoutを増やし、buffering を無効にします。これにより、ストリーミング中の token がクライアントに届きます。 - 独自のクライアントの timeout を延長します。30 秒の制限を設定した Go または Python プログラムは、推論にそれ以上かかるモデルでは失敗します。
これらすべての背後には、もう 1 つ原因があります。Ollama は同時に処理できるリクエスト数が限られており、残りをキューに入れます。そのため、遅いモデルが存在しなくても、2 番目の呼び出し元はキューで待機している間に自身の deadline を超えることがあります。サーバーログには、リクエストが失敗したのではなく、遅れて処理されたことが記録されます。複数のユーザーで 1 台の Ollama サーバーを共有するとどうなるかでは並列性の設定を説明し、VPS への基本インストールでは、これらの override が前提とするサービス設定を説明します。
FAQ
「context deadline exceeded」は Ollama で何を意味しますか?
モデルが応答する前に、リクエストの期限が切れたことを意味します。この文言は Go の context パッケージに由来するため、Go プログラムが出力しています。該当するのは Ollama コマンドラインツール、Ollama サーバー、または API を呼び出す Go アプリケーションです。これはタイムアウトであり、何かが壊れたり破損したりしたわけではありません。次に、どの層が期限を設定したかを確認します。クライアント、モデルのロード、keep_alive、num_ctx、リバースプロキシは、それぞれ独自の期限を設定するためです。
クライアントのタイムアウトと Ollama のタイムアウトのどちらを延長すべきですか?
まず測定してください。curl を使用して、サーバー上から直接 http://127.0.0.1:11434 へリクエストを送信します。curl には全体の時間制限がないためです。この呼び出しが JSON 本文を返す場合、Ollama は応答しています。期限はクライアントまたはプロキシにあるため、そちらの設定を延長します。この呼び出しも停止したままになる場合、遅延は Ollama 内部で発生しています。レスポンスの load_duration と prompt_eval_duration のフィールドから、モデルのロード中か、プロンプトの読み取り中かを確認できます。
最初のリクエストだけタイムアウトし、次のリクエストは成功するのはなぜですか?
Ollama は、メモリを解放するためにアイドル状態のモデルをアンロードします。このスケジュールは keep_alive で設定します。2026年9月時点で、ドキュメントに記載されたデフォルトは 5 分です。アイドル期間の後に送信した最初のリクエストでは、モデルがディスクから再ロードされるため、コールドスタートの時間がすべてかかります。一方、直後に送信したリクエストではモデルがメモリ上にあるため、すぐに応答します。ollama ps を実行すると、ロード済みのモデルと有効期限を確認できます。OLLAMA_KEEP_ALIVE=-1 を設定するとモデルをメモリに保持できますが、その分メモリを占有し続けます。
nginx 経由の場合だけ失敗するのはなぜですか?
nginx のドキュメントでは proxy_read_timeout のデフォルトを 60s としています。このタイムアウトはレスポンス全体ではなく、連続する 2 回の読み取りの間に適用されます。ストリーミングレスポンスではチャンクを受信するたびにタイムアウトがリセットされます。一方、"stream": false を使用して送信したリクエストは、1 回の時間枠内に完了する必要があります。そのため、チャット画面では動作してもスクリプトでは失敗します。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 をログに記録するまでの待機時間が変わるだけです。モデルがメモリに収まらない場合、マシンは swap を使用します。その結果、ロードは非常に遅くなり、タイムアウトを延長しても失敗する時点が後になるだけで、問題は解決しません。ollama --version を実行し、そのタグの envconfig/config.go を確認して、使用しているビルドのデフォルト値を調べてください。数分を要するロードは、より小さい量子化モデルに切り替えるべき兆候と考えてください。