Ollama: как исправить ошибку context deadline exceeded
Ошибка context deadline exceeded в Ollama означает истечение времени ожидания ответа от модели. Узнайте, как настроить таймауты в клиенте, сервере или Nginx для решения проблемы.
Что на самом деле означает "context deadline exceeded"
Ошибка Ollama context deadline exceeded — это сообщение о превышении времени ожидания. Часть кода на Go установила крайний срок для запроса, модель не успела завершить работу к этому моменту, и срок истёк. Ничего не упало, файлы не повреждены. Процесс продолжал выполняться, когда время вышло.
Эта формулировка взята из стандартного пакета Go context, и это само по себе полезная подсказка. Клиент на Python, построенный на httpx, выдаст вместо этого httpx.ReadTimeout. Браузер покажет обычную сетевую ошибку. Если вы видите именно эти слова, значит, программа на Go прекратила ожидание: это может быть инструмент командной строки Ollama, сам сервер Ollama или приложение на Go, вызывающее API (интерфейс прикладного программирования).
Задействовано пять уровней. Три из них устанавливают собственный крайний срок: ваш клиент, тайм-аут загрузки модели на сервере и обратный прокси-сервер. Два других, keep_alive и num_ctx, не устанавливают крайний срок, но определяют объём работы, который должен быть выполнен за один раз. Они дают сбой в разных точках, и для каждой требуется своё решение, поэтому вся задача сводится к тому, чтобы понять, какой именно уровень вызывает ошибку.
- Ваш HTTP-клиент, который задал запросу фиксированный бюджет времени.
- Тайм-аут загрузки модели на сервере Ollama, который срабатывает, пока большая модель впервые считывается с диска.
keep_alive, который выгружает модель между запросами, поэтому следующий вызов снова оплачивает стоимость загрузки.num_ctx, достаточно большой, чтобы обработка только одного промпта занимала минуты на системе без GPU.- Обратный прокси-сервер, такой как nginx или Traefik, разрывающий соединение до того, как Ollama успела ответить.
Двигайтесь по этому списку сверху вниз. Каждый шаг ниже исключает один уровень из рассмотрения, чтобы вы перестали гадать.
Воспроизведение через 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}'Статус 504, выведенный после подозрительно «круглого» количества секунд (60.0 или 30.0), указывает на таймаут прокси. Прокси используют стандартные значения по умолчанию. Модель не может завершать работу ровно через 60.000 секунд два раза подряд. Если прямой вызов отклоняется мгновенно, а не медленно, у вас проблема с прослушиванием порта, а не с ограничением по времени; в этом случае обратитесь к разделу на каком адресе Ollama слушает порт 11434.
Мониторинг лога сервера во время выполнения запроса
Откройте вторую сессию и отслеживайте лог службы, затем повторно отправьте запрос.
journalctl -u ollama --no-pager --follow --pager-endПри успешном «холодном» старте в логах отображается загрузка модели, запуск исполнителя (runner) и последующая обработка запроса. Ошибка загрузки выглядит иначе; именно эта строка указывает на то, что сервер превысил собственный тайм-аут загрузки:
Error: timed out waiting for llama runner to start - progress 0.00 -Это сообщение означает, что процесс модели не успел завершить запуск в рамках выделенного серверу времени. Значение прогресса показывает, на каком этапе произошел сбой. Значение 0.00 означает, что исполнитель не предоставил никаких данных до истечения крайнего срока, что обычно указывает на продолжающееся чтение файла или использование сервером swap-памяти. Для получения более подробной информации в процессе загрузки перезапустите службу с установленной переменной 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 должно снизиться почти до нуля, так как модель уже находится в оперативной памяти. Если значение не снижается, значит, модель выгружается между запусками — это случай 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. Значение в этом файле является значением по умолчанию, с которым был скомпилирован ваш бинарный файл. Установите собственное значение через drop-in файл systemd.
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 года указано значение по умолчанию — 5 минут. Поэтому чат-приложение, которое используется раз в час, перезагружает модель при каждом сообщении, и каждое сообщение оплачивает полную стоимость «холодного» старта. Запрос, который превышает время ожидания, — это первый запрос после периода простоя, что соответствует поведению, которое пользователи описывают как случайное.
Проверьте, что сейчас находится в памяти:
ollama ps
curl -s http://127.0.0.1:11434/api/psПустой список или время истечения через несколько минут подтверждают это. keep_alive принимает строку длительности, например "10m" или "24h", простое число секунд, 0 для немедленной выгрузки или отрицательное число, чтобы удерживать модель в памяти бесконечно. Установите это для каждого запроса или задайте OLLAMA_KEEP_ALIVE в настройках сервиса для всех запросов. Значение в запросе имеет приоритет: документация Ollama гласит, что параметр API keep_alive переопределяет настройку OLLAMA_KEEP_ALIVE, поэтому клиент, отправляющий свой keep_alive, всё равно будет выгружать модель по собственному графику.
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"keep_alive": -1
}'Запрос с указанием модели, но без промпта, загружает модель и возвращает ответ. Это документированный способ «прогрева» системы после перезагрузки, и его стоит добавить в небольшой юнит systemd, чтобы никто не ждал первого «холодного» старта после перезагрузки сервера. Цена этого решения очевидна: закреплённая в памяти модель занимает её постоянно, поэтому на сервере с малым объёмом памяти можно закрепить одну модель, а не четыре. Удержание модели в памяти между запросами содержит расчёты памяти и пример юнита для прогрева.
Почему большое значение num_ctx приводит к тайм-ауту до генерации первого токена
Перед тем как модель начнет что-либо писать, она должна прочитать весь ваш промпт. Этот этап называется префиллом (prefill), и именно его измеряет prompt eval. Параметр num_ctx задает длину контекста, что одновременно выполняет две задачи. Он ограничивает количество токенов, которые модель может учитывать, и определяет размер KV-кэша (key value cache), который сервер выделяет заранее. Оба фактора увеличивают объем вычислений.
На сервере без GPU префилл происходит медленно, и время его выполнения линейно зависит от количества токенов в промпте. При вставке длинного документа в чат процесс префилла может занимать минуты, в течение которых клиент не видит никакого ответа, так как потоковая передача еще не началась. Клиент достигает лимита времени ожидания и сообщает об ошибке превышения контекста (context deadline exceeded), хотя сервер все это время продолжал работу. Проверьте это с помощью показателей из предыдущего раздела. Отправьте длинный промпт и посмотрите значения prompt_eval_count и prompt_eval_duration, которые Ollama определяет как время, затраченное на обработку некэшированных токенов промпта. Если там указаны минуты при небольшом eval_duration, значит, это префилл. Поскольку учитываются только некэшированные токены, повторный запуск того же промпта на модели, которая все еще загружена в память, может показать гораздо меньшее время, поэтому сравнивайте только первые запуски. Чтобы увидеть, во сколько обходится увеличение кэша, запустите промпт с "options": {"num_ctx": 2048}, а затем с 32768, и также обратите внимание на load_duration, так как время, затраченное на загрузку модели, отражается там, а не в prompt_eval_duration.
Значение по умолчанию для сервера берется из OLLAMA_CONTEXT_LENGTH, а параметр num_ctx в объекте options для каждого отдельного запроса переопределяет его. Распространенная ошибка — увеличивать это значение до максимально заявленного для модели только потому, что такой максимум существует. Выделение KV-кэша может вытеснить модель из оперативной памяти и привести к тому, что рабочая конфигурация начнет использовать своп. В разделе Выбор 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: таймаут «устанавливается только между двумя последовательными операциями чтения, а не на передачу всего ответа целиком». Потоковый ответ сбрасывает таймер при получении каждого фрагмента, поэтому потоковые чаты не прерываются. Запрос с "stream": false не отправляет ничего до завершения ответа, поэтому вся генерация должна уложиться в этот временной интервал. Именно поэтому одна и та же модель работает в окне чата, но выдает таймаут при вызове из скрипта. Если же клиентом выступает Claude Code, а между ним и моделью стоят LiteLLM и nginx, звеньев в цепочке становится больше, и разбор ошибки Request timed out в Claude Code поможет понять, какое из них держит ответ.
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 определяет время ожидания заголовков ответа после отправки запроса, значение ноль означает отсутствие таймаута. Сервис должен ссылаться на транспорт по имени через serversTransport: ollama, иначе вы редактируете блок, который никем не используется.
Модель с меньшей квантованием загружается быстрее, так как данных для чтения меньше
Квантование — это точность, с которой хранятся веса модели. Более низкая точность означает меньший размер файла, а загрузка модели — это в основном чтение файла с диска в память.
Данные, на которых построен график
[
{
"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 ГБ. Полноточная версия той же модели занимает 16 ГБ: это более чем в три раза больше данных для чтения и более чем в три раза больше памяти для размещения. На арендованном сервере с общим хранилищем эта разница — это грань между успешной загрузкой и срабатыванием тайм-аута. Определение того, какая модель поместится в вашу RAM — это проверка, которую нужно выполнить перед скачиванием чего-либо объёмного.
Что изменить на арендованном сервере
Применяйте эти настройки по одной в порядке, указанном результатами замеров, и после каждого изменения повторно запускайте команду замера времени.
- Закрепите модель с помощью
OLLAMA_KEEP_ALIVE=-1и прогрейте её при загрузке, чтобы запросы пользователей не тратили время на ожидание загрузки. Затем убедитесь, что ни один клиент не передает свой собственныйkeep_alive, так как значение в запросе переопределяет настройки сервера. - Уменьшите
num_ctxдо значения, которое действительно необходимо для ваших промптов: это сократит время префилла (prefill) и освободит память, занимаемую KV-кэшем. - Используйте квантование меньшего размера, чтобы при загрузке считывалось меньше байтов, а у модели оставалось место для кэша.
- Увеличьте
proxy_read_timeoutв Nginx илиresponseHeaderTimeoutв Traefik и отключите буферизацию, чтобы потоковые токены доходили до клиента. - Увеличьте таймаут в своем клиенте, так как программа на Go или Python с лимитом в 30 секунд завершится с ошибкой при работе с любой моделью, которая «думает» дольше.
За всеми этими причинами скрывается еще одна. Ollama обрабатывает ограниченное количество запросов одновременно, а остальные ставит в очередь. В результате второй пользователь может ожидать в очереди до истечения своего лимита времени, даже если сама модель работает быстро. В логах сервера будет видно, что запрос был обработан с задержкой, а не завершился ошибкой. В Что происходит, когда несколько пользователей используют один сервер Ollama описаны настройки параллелизма, а в базовая установка на VPS — настройка сервиса, на которую опираются эти изменения.
FAQ
Что означает ошибка "context deadline exceeded" в Ollama?
Это означает, что время ожидания ответа от модели истекло. Фраза взята из пакета context языка Go, поэтому её выводит программа на Go: консольная утилита Ollama, сервер Ollama или приложение, обращающееся к API. Это таймаут, поэтому ничего не сломано и не повреждено. Следующий шаг — определить, какой уровень установил ограничение, так как клиент, процесс загрузки модели и reverse proxy задают свои лимиты, а 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 минут, проверено в октябре 2026 года. Первый запрос после периода простоя вызывает загрузку модели с диска и требует времени на «холодный старт», в то время как запрос, отправленный сразу после, находит модель в памяти и возвращает ответ быстро. Запустите ollama ps, чтобы увидеть, что загружено и когда истекает срок действия. Установите OLLAMA_KEEP_ALIVE=-1, чтобы удерживать модель в памяти, но учитывайте, что память будет занята постоянно. Клиент, который отправляет свой собственный keep_alive, переопределяет эту настройку, поэтому проверьте и настройки клиентов.
Почему ошибка возникает только при работе через nginx?
В документации nginx для proxy_read_timeout указано значение по умолчанию 60s, и этот таймаут применяется между двумя последовательными операциями чтения, а не ко всему ответу целиком. Потоковый ответ сбрасывает этот таймер при получении каждого фрагмента, в то время как запрос, отправленный с "stream": false, должен завершиться в рамках одного окна. Именно поэтому чат работает, а скрипт выдает ошибку. Ищите upstream timed out (110: Connection timed out) while reading response header from upstream в логе ошибок nginx, затем увеличьте proxy_read_timeout и настройте proxy_buffering off.
Ускоряет ли загрузку увеличение OLLAMA_LOAD_TIMEOUT?
Нет. Это лишь меняет время, которое сервер ждет перед тем, как сдаться и записать в лог timed out waiting for llama runner to start. Если модель не помещается в память, машина начинает использовать swap, загрузка замедляется, и увеличение таймаута лишь откладывает ошибку, не исправляя её. Проверьте значение по умолчанию для вашей сборки, выполнив ollama --version и прочитав envconfig/config.go для этого тега; если загрузка занимает минуты, это сигнал к тому, чтобы использовать модель с меньшей квантованностью.