Коротко
- На Windows 2026.9.2/9.3 у одного агента
openclaw-agent.sqlite-walдорос до 2865 МБ, Gateway жив, но/healthzотвечает отказом соединения: старт висит на захвате SQLite-лока. wal_autocheckpoint=1000стоит по умолчанию, а чекпойнт не идёт. 97% WAL это повторные перезаписи тех же страниц.- Офлайн
wal_checkpoint(TRUNCATE)снимает проблему за ~20 с, живой чекпойнт только подрезает пик, и WAL тут же растёт. - Поставьте размер
*.sqlite-walв мониторинг и держите наготове сценарий стоп-старта Gateway выше своего порога.
Сверено с документацией OpenClaw 2026.9.7, 2 октября 2026.
У одного агента на Windows-хосте файл openclaw-agent.sqlite-wal за дни вырос до 2865 МБ. После ручного офлайн-чекпойнта он упал до нуля и за два дня вернулся к 1477 МБ. Процесс Gateway при этом жив, но порт не биндится. /healthz отдаёт отказ соединения, а дельта лога за 25 секунд равна нулю байт.
Как отличить «большой» WAL от залипшего
97% WAL это повторные перезаписи одних и тех же страниц. Из 2865 МБ на «свежую» запись пришлось 72.5 МБ (2.5%). Из 1477 МБ пришлось 73.6 МБ (5%). Это сигнатура зависшего чекпойнта, а не настоящего объёма данных.
Картина pragma при этом нормальная: integrity_check = ok, wal_autocheckpoint = 1000, journal_mode = wal. Пока WAL измеряется гигабайтами, Gateway не биндит порт и старт висит на захвате SQLite-лока.
Диагностика за 30 секунд
Сначала найдите самый большой WAL по всем агентам. Сразу видно, у кого проблема.
Get-ChildItem $env:USERPROFILE\.openclaw\ -Recurse -Filter *.sqlite-wal -EA 0 |
Sort Length -Desc | Select -First 5 |
% { "{0} MB`t{1}" -f [math]::Round($_.Length/1MB,1), $_.FullName }
Запись больше нескольких сотен мегабайт это повод копать. Затем проверьте, жив ли процесс и отвечает ли порт. При зависшем чекпойнте процесс жив, но /healthz отдаёт exit 7 (отказ соединения), а дельта лог-файла за 25 секунд равна нулю байт.
Если порт не отвечает, а процесс на месте, смотрите в лог на subsystem=sqlite/transaction и Gateway restart timed out after 181s waiting for health checks. Это и есть «старт висит на захвате лока».
Офлайн wal_checkpoint(TRUNCATE) снимает клин
Попытки сделать wal_checkpoint(TRUNCATE) на живой базе дают busy=1, все кадры чекпойнтятся, но без сброса файла. Помогает только офлайн, со стопом Gateway, эксклюзивным доступом и бэкапом главной базы. WAL в бэкап не копируйте.
schtasks /Change /TN "OpenClaw Gateway" /DISABLE
Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
? CommandLine -like "*openclaw*" | % { Stop-Process -Id $_.ProcessId -Force }
Start-Sleep 8
$db = "$env:USERPROFILE\.openclaw\agents\agent-a\agent\openclaw-agent.sqlite"
copy $db "$db.bak" -Force
& "C:\Program Files\nodejs\node.exe" -e "
const {DatabaseSync}=require('node:sqlite');
const d=new DatabaseSync(process.argv[1]);
console.log(JSON.stringify(d.prepare('PRAGMA integrity_check').get()));
console.log(JSON.stringify(d.prepare('PRAGMA wal_checkpoint(TRUNCATE)').get()));
d.close();" "$db"
DatabaseSync всасывает WAL при открытии, поэтому wal_checkpoint(TRUNCATE) часто возвращает busy:0, log:0, checkpointed:0 и выглядит как пустая операция. Судить надо по размеру: главный файл вырос, openclaw-agent.sqlite-wal ушёл в 0 МБ. Это известная ловушка при отладке. Затем верните Gateway обратно через Планировщик задач и проверьте /healthz.
Границы применимости
Симптом воспроизведён на Windows 2026.9.2/9.3 (Server, Node v24.18.0) и отдельно на 2026.8.2. Есть и второй сценарий: залипает state/openclaw.sqlite-wal (0 → 691 МБ за ~12 минут) на 2026.9.4. Там виноват не base64, а поток мелких записей под нагруженным event loop.
Что проверить у себя
- Найти самый большой WAL командой из раздела про диагностику. Запись больше нескольких сотен МБ уже повод действовать.
- Собрать набор для офлайн-чекпойнта:
schtasks /Change /TN "OpenClaw Gateway" /DISABLE, остановкаnode.exeпоCommandLine -like "*openclaw*", копия основной базы с расширением.bak, запускnodeсPRAGMA wal_checkpoint(TRUNCATE)черезnode:sqliteDatabaseSync. - Судить о результате по размеру файлов: главный
openclaw-agent.sqliteвырос,openclaw-agent.sqlite-walушёл в 0 МБ. Возвратbusy:0, log:0, checkpointed:0при этом нормален, если WAL при открытии уже втянут. - Завести сценарий-сторож: каждые 15 минут мерять
*.sqlite-wal, выше 50 МБ пробовать живойwal_checkpoint(TRUNCATE), выше 200 МБ выполнять стоп Gateway, офлайн TRUNCATE, старт. Контрольное время обслуживания в репро: ~26 с от начала до конца. - Следить за логом
subsystem=sqlite/transactionс порогомthresholdMs=1000и строкой тайм-аута рестарта по ожиданию health-проверок. - Проверить настройки сессии: в
session.maintenanceбыли толькоmaxDiskBytes: 500mbиhighWaterBytes: 400mbбезpruneAfterиmaxEntries, поэтому данные не удалялись. - Проверить, нет ли в
transcript_eventsкрупныхtoolResultотview_image. Это отдельный вектор роста (отдельный тикет #143973), который один способен перегнатьwal_autocheckpoint.