Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

[Bug]: SQLite WAL is never checkpointed — clean exit leaves a multi-MB -wal file

Ouverte
#505 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
74/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
sqlite, typescript
Domaine
database

Piste de recherche

Start with packages/local-runtime-v2/src/infra/db/client.ts and runtime.ts to trace database initialization and the closeRuntime() shutdown path. Add the proposed checkpoint behavior and tests for WAL truncation with rows preserved and for closed clients; run the new tests and packages/local-runtime-v2/src/services.test.ts. Done means clean startup and shutdown truncate the WAL without losing committed rows or making close fail.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

tui
Product or interface

CLI - interactive TUI

Version
  • @minimax-ai/code 0.6.12 (npm, Linux)
  • Reproduced from source at commit 9a935605956c4500e9cb415f29258e2887e97817 (repository package version 0.6.5)
  • Node.js 24.21.0
Platform

Linux

OS version and architecture

Linux 7.2.9 x64 (NixOS)

Issue area

File / workspace / path / encoding

Steps to reproduce
  1. Use mcode normally for a few sessions, or run one mcode exec turn in a fresh profile.
  2. Exit cleanly (no kill, no crash).
  3. Inspect the SQLite files:
ls -l ~/.minimax/v2/sqlite/runtime-state.sqlite*

Minimal one-turn repro:

mcode exec --permission off "Reply with exactly OK"
ls -l ~/.minimax/v2/sqlite/runtime-state.sqlite*
Expected and actual behavior

Expected: a clean exit leaves a small or zero-byte -wal, with committed pages checkpointed into the main database file.

Actual: the WAL persists at multi-megabyte size after the process exits. On a fresh profile, one trivial turn leaves:

runtime-state.sqlite        4 KB
runtime-state.sqlite-wal 3,798 KB

The main DB is only 4 KB because the turn's data still lives in the WAL. Nothing in 0.6.12 ever runs wal_checkpoint.

Evidence

Same-revision comparison (build from 9a93560, identical one-turn exec, isolated HOME, measured after exit):

Build runtime-state.sqlite -wal
HEAD (unpatched) 4 KB 3,283 KB
HEAD + checkpoint patch (below) 964 KB 0 KB

Installed 0.6.12 shows the same: 3,798 KB -wal, 4 KB main file.

Startup reclaim: a profile left with a 3,798 KB WAL, started with the patched build, ends at 0 KB with the DB at 1,116 KB.

Cost on a real database (247 MB main file, 17.6 MB WAL): PRAGMA wal_checkpoint(TRUNCATE) takes 26.7 ms and takes the WAL from 17.6 MB to 0. A real checkpoint of 21 MB / 5,334 frames (autocheckpoint disabled) takes 70.7 ms.

Static check of the 0.6.12 bundle and upstream main: PRAGMA journal_mode = WAL is set in packages/local-runtime-v2/src/infra/db/client.ts, and there is no wal_checkpoint, journal_size_limit, auto_vacuum, or PRAGMA optimize anywhere. main still has no checkpoint, and no open PR implements one.

Root cause
  • client.ts opens the DB with journal_mode = WAL, busy_timeout, foreign_keys — and nothing else.
  • close() closes the handle without a checkpoint.
  • The only close path is runtime.ts closeRuntime(); no startup or periodic checkpoint runs.
  • SQLite's default wal_autocheckpoint = 1000 pages backfills pages into the main DB but does not reset the WAL file, so the -wal keeps its high-water size.
Proposed fix

Two checkpoints, ~18 added lines:

  1. DatabaseClient.checkpoint(mode = 'PASSIVE') — no-op when closed, best-effort PRAGMA wal_checkpoint(<mode>).
  2. close() calls checkpoint('TRUNCATE') before closing.
  3. After initializeDatabase() resolves in runtime.ts, a synchronous checkpoint('TRUNCATE') (measured as db_checkpoint_ms) reclaims a WAL left by a crash or a previous long session.

Plus two tests: truncation shrinks the WAL to 0 while preserving rows, and no throw on closed/never-opened clients.

Deliberately excluded: journal_size_limit (measured as a null result — 0, 4 MiB and -1 all left the same 21 MB WAL) and wal_autocheckpoint=1000 (already SQLite's default).

Validation
  • tsc -p tsconfig.standalone.json --noEmit → exit 0
  • new test → 2/2; packages/local-runtime-v2/src/services.test.ts → 64/64
  • scripts/source-inventory.mjs → 4,356 files, passed
  • build → bundle contains wal_checkpoint and db_checkpoint_ms
  • end-to-end numbers above, on an otherwise idle profile
Scope and limitations
  • This is not a fix for #496's retention/RSS report. It does not touch the retention queue, orphan rows, transcript storage, or RSS; it only bounds the WAL file at startup and shutdown.
  • Long-running sessions are not covered: the file is truncated at start/close, not periodically.
  • The TUI shutdown path shares closeRuntime() with exec by code inspection, but only exec was measured end-to-end.
  • A checkpoint attempted while another connection holds a write transaction fails with database table is locked; the error is deliberately swallowed so shutdown cannot fail. It degrades to “no early truncate”, not a crash, but it is not logged.
  • A legacy v1 connection to the same database is opened at startup and never closed in production; a late write from it can recreate WAL frames after the checkpoint. Not addressed here.
  • Timings were taken on a host at loadavg ~5.5; treat them as indicative.
Workaround on released versions
sqlite3 ~/.minimax/v2/sqlite/runtime-state.sqlite "PRAGMA wal_checkpoint(TRUNCATE);"

after exiting mcode.

Before submitting
  • I have searched existing issues.
  • I have included my version and removed sensitive information.
Langage dominant
TypeScript
Étoiles
2k
Forks
259
Merge moyen
7 h 56 min
PR mergées (30 j)
126

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de MiniMax-AI/minimax-code

Toutes les issues de MiniMax-AI/minimax-code

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.