SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor

Ollamaのcontext deadline exceededを解決する方法

Ollamaのエラー「context deadline exceeded」は、モデルの応答前にタイムアウトした合図です。クライアント、モデル読み込み、nginxのどこで期限が設定されたか切り分けます。

「context deadline exceeded」が実際に意味すること

Ollama のエラー context deadline exceeded は、タイムアウトの通知です。Go コードのどこかでリクエストに期限が設定され、モデルがその期限内に処理を終えられず、期限が切れました。クラッシュしたわけでも、ファイルが破損したわけでもありません。時間切れになった時点でも処理は実行中でした。

この文言は Go の標準 context パッケージに由来します。これだけでも有用な手掛かりになります。httpx を基盤とする Python クライアントでは、代わりに httpx.ReadTimeout が発生します。ブラウザーでは、単純なネットワークエラーが表示されます。この正確な文言が表示されているなら、Go プログラムが待機を打ち切ったということです。Ollama のコマンドラインツール、Ollama サーバー自体、または API(アプリケーションプログラミングインターフェイス)を呼び出す Go アプリケーションのいずれかです。

関係する層は 5 つあります。そのうち 3 つは、それぞれ独自に期限を設定します。クライアント、サーバーのモデル読み込みタイムアウト、リバースプロキシです。残りの 2 つである keep_alive と num_ctx は期限を設定しませんが、1 つの期限内に収める必要がある処理量を決めます。失敗する箇所はそれぞれ異なり、必要な対処も異なります。そのため、エラーの原因となっている層を特定することが重要です。

  1. リクエストに固定の時間予算を設定した HTTP クライアント。
  2. Ollama サーバーのモデル読み込みタイムアウト。大きなモデルを初回にディスクから読み込んでいる間に発生します。
  3. keep_alive。リクエスト間でモデルをアンロードするため、次の呼び出しで再び読み込み時間がかかります。
  4. CPU のみの環境では、プロンプト処理だけで数分かかるほど大きな num_ctx。
  5. 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 400

curl は独自の全体制限時間を設けず、接続タイムアウトだけを設定します。そのため、このコマンドは 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 年 10 月時点のデフォルト値を 5 分としています。そのため、1 時間に 1 回だけ使うチャットアプリでは、メッセージを送るたびにモデルが再読み込みされ、毎回コールドスタートの時間がかかります。タイムアウトするリクエストは静止期間の後に送られる最初のリクエストです。このため、利用者にはランダムな問題に見えます。

現在メモリ上に保持されている内容を確認します。

ollama ps
curl -s http://127.0.0.1:11434/api/ps

空の一覧、または数分後に期限切れになる状態であれば、これが原因です。keep_alive には "10m" や "24h" のような期間文字列、秒数を表す単純な数値、即時にアンロードする 0、モデルを無期限にメモリへ保持する負の数を指定できます。リクエストごとに設定することも、サービスに OLLAMA_KEEP_ALIVE を設定してすべてのリクエストに適用することもできます。リクエスト側の値が優先されます。Ollama のドキュメントによると、keep_alive API パラメーターは OLLAMA_KEEP_ALIVE 設定を上書きします。そのため、クライアントが独自の 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 はコンテキスト長を設定します。これは同時に2つの役割を持ちます。モデルが考慮できるトークン数の上限を設定し、サーバーが事前に確保する KV キャッシュ(key value cache)のサイズを決めます。どちらも処理量を増やします。

CPU のみのサーバーでは prefill が遅く、プロンプトのトークン数に対して線形に時間が増えます。チャットに長い文書を貼り付けると、ストリーミングがまだ始まっていないため、クライアントには何も表示されないまま prefill に数分かかることがあります。クライアントは期限に達して context deadline exceeded を報告しますが、その間もサーバーは処理を続けています。前のセクションの数値で確認できます。長いプロンプトを送信し、prompt_eval_count と prompt_eval_duration を読み取ってください。Ollama はこれらを、キャッシュされていないプロンプトトークンの評価にかかった時間として定義しています。ここが数分で、eval_duration が小さい場合は prefill が原因です。数えるのはキャッシュされていないトークンだけなので、モデルがロードされたままの状態で同じプロンプトを繰り返すと、報告される時間が大幅に短くなることがあります。そのため、最初の実行結果を比較してください。大きなキャッシュのコストを確認するには、"options": {"num_ctx": 2048} を指定してプロンプトを実行し、次に 32768 を指定して実行します。load_duration も確認してください。モデルのロードにかかった時間はそこに報告され、prompt_eval_duration には報告されないためです。

サーバーのデフォルト値は OLLAMA_CONTEXT_LENGTH から取得されます。options オブジェクト内のリクエスト単位の num_ctx を指定すると、その値が上書きされます。最大値が存在するからという理由だけで、モデルが公開している最大値まで引き上げるのはよくある誤りです。KV キャッシュの確保によってモデルが 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 upstream

nginx のドキュメントで重要なのは、このタイムアウトが「レスポンス全体の送信ではなく、連続する 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 を名前で参照する必要があります。そうしないと、使用されていない設定ブロックを編集しただけになります。

低い量子化では読み込むデータ量が少ないため、より速くロードできます

量子化とは、重みを保存する精度です。低い精度ではファイルが小さくなります。モデルのロードでは、主にそのファイルをディスクからメモリへ読み込みます。

グラフPublished download sizes for llama3.1 8B on the ollama.com library, October 2026
このグラフのデータ
[
  {
    "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 に収まるモデルの確認を実行してください。

レンタルサーバーで変更する項目

測定結果が示す順に、1 つずつ適用してください。各変更の後に、タイミング確認用のコマンドを再実行します。

  1. OLLAMA_KEEP_ALIVE=-1 でモデルを固定し、起動時にウォームアップします。これにより、ユーザーリクエストごとにロード時間が発生しなくなります。次に、クライアントが独自の keep_alive を送信していないことを確認します。リクエスト内の値がサーバー設定を上書きするためです。
  2. プロンプトで実際に必要な値まで num_ctx を下げます。これにより prefill が短くなり、KV cache が確保していたメモリを解放できます。
  3. より小さい量子化モデルを取得します。ロード時に読み込むバイト数が減り、モデルが cache 用の領域を確保できます。
  4. nginx の proxy_read_timeout または Traefik の responseHeaderTimeout を増やし、buffering を無効にします。これにより、ストリーミング中の token がクライアントに届きます。
  5. 自分のクライアントの timeout を延長します。30 秒の制限を設定した Go または Python プログラムは、推論にそれ以上かかるモデルに対して失敗するためです。

これらすべての背後には、もう 1 つ原因があります。Ollama は同時に処理できるリクエスト数が限られており、超過したリクエストをキューに入れます。そのため、遅いモデルが動作していなくても、2 番目の呼び出し元はキュー内で待機している間に自身の deadline を超えることがあります。サーバーログには、リクエストが失敗したのではなく、遅れて処理されたことが記録されます。複数のユーザーが 1 台の Ollama サーバーを共有した場合の動作では並列処理の設定を説明し、VPS への基本インストールでは、これらの上書き設定が前提とするサービス構成を説明します。

FAQ

Ollama で「context deadline exceeded」とはどういう意味ですか?

モデルが応答する前に、リクエストの期限が切れたことを意味します。この文言は 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 で設定されたスケジュールに従ってアンロードします。ドキュメントに記載されたデフォルトは 5 minutes です。これは October 2026 に確認した値です。アイドル期間後の最初のリクエストでは、モデルをディスクから再ロードするため、コールドスタートの全処理時間がかかります。一方、直後に送信したリクエストではモデルがメモリ上に残っているため、すぐに返ります。ollama ps を実行すると、ロード済みのモデルと有効期限を確認できます。OLLAMA_KEEP_ALIVE=-1 を設定するとモデルをメモリに保持できますが、その分メモリを占有し続けます。クライアントが独自の keep_alive を送信すると、この設定は上書きされます。クライアント側も確認してください。

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 を使用します。ロードは遅くなり、タイムアウトを延長しても失敗する時点が後ろにずれるだけで、問題は解決しません。使用している build のデフォルトを確認するには、ollama --version を実行し、その tag の envconfig/config.go を読み取ります。数 minutes かかるロードは、より小さい quantisation を取得すべき兆候と考えてください。