Ollama: как исправить ошибку context deadline exceeded
Ошибка context deadline exceeded в Ollama означает истечение времени ожидания запроса. Узнайте, как найти виновный слой: настройки HTTP-клиента, Nginx или параметры keep_alive.
Что на самом деле означает ошибка "context deadline exceeded"
Ошибка context deadline exceeded в Ollama — это уведомление о превышении времени ожидания. Часть кода на Go установила крайний срок выполнения запроса, модель не успела завершить работу к этому моменту, и срок истёк. Никаких сбоев не произошло, файлы не повреждены. Процесс продолжал выполняться, когда время вышло.
Эта формулировка взята из стандартного пакета context языка Go, что само по себе является полезной подсказкой. Python-клиент, построенный на httpx, вместо этого вызывает httpx.ReadTimeout. Браузер в такой ситуации показывает обычную сетевую ошибку. Если вы видите именно эти слова, значит, программа на Go прекратила ожидание: это может быть командная строка Ollama, сам сервер Ollama или приложение на Go, вызывающее API (интерфейс прикладного программирования).
Существует пять уровней, на которых может быть установлен этот крайний срок. Они вызывают сбои в разных точках, и для каждого требуется своё решение, поэтому основная задача — определить, какой именно уровень сработал.
- Ваш HTTP-клиент, который выделил на запрос фиксированный бюджет времени.
- Тайм-аут загрузки модели на сервере Ollama, который срабатывает, если большая модель впервые считывается с диска.
keep_alive, который выгружает модель между запросами, из-за чего при каждом следующем вызове приходится снова тратить время на загрузку.num_ctx, настолько большой, что одна только обработка промпта занимает минуты на системе без GPU.- Reverse proxy, например 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 в настройках сервиса для всех запросов.
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, хотя сервер все это время продолжал работать. Проверьте это с помощью чисел из предыдущего раздела: запустите один и тот же запрос с "options": {"num_ctx": 2048}, а затем с 32768, и сравните prompt_eval_duration.
Значение по умолчанию для сервера берется из OLLAMA_CONTEXT_LENGTH, а параметр num_ctx в объекте options переопределяет его для конкретного запроса. Распространенная ошибка — увеличивать это значение до максимально заявленного для модели только потому, что такой максимум существует. Выделение памяти под KV-кэш может привести к нехватке оперативной памяти, из-за чего рабочая конфигурация начнет использовать 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: таймаут «устанавливается только между двумя последовательными операциями чтения, а не на передачу всего ответа целиком». Потоковый ответ сбрасывает таймер при получении каждого фрагмента, поэтому потоковые чаты не прерываются. Запрос с "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 определяет время ожидания заголовков ответа после отправки запроса, значение ноль означает отсутствие таймаута. Сервис должен ссылаться на транспорт по имени через 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 ГБ. Полноточная сборка той же модели занимает 16 ГБ — это более чем в три раза больше байтов для чтения и в три раза больше памяти для размещения. На арендованном сервере с общим хранилищем эта разница определяет, завершится ли загрузка успешно или будет прервана по тайм-ауту. Определение того, какая модель поместится в вашу RAM — это проверка, которую необходимо выполнить перед загрузкой любых крупных файлов.
Что изменить на арендованном сервере
Применяйте эти меры по одной в том порядке, в котором на них указывают результаты замеров, и после каждого изменения повторно запускайте команду замера времени.
- Закрепите модель в памяти с помощью
OLLAMA_KEEP_ALIVE=-1или прогрейте её при загрузке, чтобы ни один запрос пользователя не оплачивал стоимость загрузки. - Уменьшите
num_ctxдо значений, которые действительно требуются вашим промптам: это сократит время префилла и освободит память, занимаемую KV-кэшем. - Используйте квантование меньшего размера, чтобы при загрузке считывалось меньше байтов, а модель оставляла место для кэша.
- Увеличьте
proxy_read_timeoutв Nginx илиresponseHeaderTimeoutв Traefik и отключите буферизацию, чтобы потоковые токены доходили до клиента. - Увеличьте таймаут в вашем клиенте, так как программа на Go или Python с лимитом в 30 секунд завершится с ошибкой при работе с любой моделью, которая «думает» дольше.
За всеми этими причинами скрывается ещё одна. Ollama обрабатывает ограниченное количество запросов одновременно, а остальные ставит в очередь. В результате второй пользователь может ожидать в очереди до истечения своего лимита времени, даже если сама модель работает быстро. В логе сервера будет видно, что запрос был обработан с задержкой, а не завершился ошибкой. Что происходит, когда несколько человек используют один сервер Ollama описывает настройки параллелизма, а базовая установка на VPS — настройку сервиса, на которую опираются эти параметры.
FAQ
Что означает ошибка "context deadline exceeded" в Ollama?
Это означает, что время ожидания запроса истекло до того, как модель успела ответить. Эта фраза исходит из пакета context языка Go, поэтому её выводит программа на Go: интерфейс командной строки Ollama, сервер Ollama или приложение на Go, вызывающее API. Это таймаут, поэтому ничего не сломано и не повреждено. Следующий шаг — определить, какой уровень установил ограничение по времени, так как клиент, процесс загрузки модели, keep_alive, num_ctx и reverse proxy устанавливают свои собственные лимиты.
Нужно ли увеличивать таймаут клиента или таймаут 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, чтобы удерживать модель в памяти, но учитывайте, что память будет занята постоянно.
Почему ошибка возникает только при работе через 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 для соответствующего тега; если загрузка занимает минуты, это сигнал к тому, чтобы использовать модель с меньшей квантованием.