jackwener/OpenCLI · warning · CommandExecutionError

Trae is actively writing (database.db-wal touched ${(ageMs /

Error message

Trae is actively writing (database.db-wal touched ${(ageMs / 1000).toFixed(1)}s ago).

What it means

checkAgentDbQuiet is a concurrency guard: before mutating Trae SOLO's ai-agent SQLite state, it checks the modification time of database.db-wal (SQLite write-ahead log). If the WAL was touched within windowSec (default 5s), Trae is assumed to be actively writing and the library refuses to mutate the DB to avoid corruption or lost writes.

Source

Thrown at clis/trae-solo/_fs.js:113

}

// Atomically update skill-config.json — read, mutate via callback, write
// via tmp + rename to avoid Trae seeing a half-written file.
export function updateSkillConfig(mutate) {
    const conf = readSkillConfig();
    mutate(conf);
    const tmp = TRAE_SKILL_CONFIG + '.tmp-' + process.pid;
    fs.writeFileSync(tmp, JSON.stringify(conf, null, 4));
    fs.renameSync(tmp, TRAE_SKILL_CONFIG);
}

// Refuse to mutate ai-agent on-disk state if database.db-wal was touched
// in the last `windowSec` seconds — Trae is probably writing.
export function checkAgentDbQuiet(windowSec = 5) {
    if (!fs.existsSync(TRAE_DB_WAL)) return; // first run
    const ageMs = Date.now() - fs.statSync(TRAE_DB_WAL).mtimeMs;
    if (ageMs < windowSec * 1000) {
        throw new CommandExecutionError(
            `Trae is actively writing (database.db-wal touched ${(ageMs / 1000).toFixed(1)}s ago).`,
            `Wait ${windowSec}+ s for Trae to settle, or quit Trae SOLO before mutating state.`,
        );
    }
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Close or quit the Trae SOLO application before running the mutating command
  2. Wait at least windowSec (5s, or pass a larger windowSec) and retry
  3. Retry in a loop with backoff until the WAL is quiet
  4. Temporarily stop background Trae agents/sync that keep writing to the DB

Example fix

// before
await traeSoloCli.config.set(k, v); // throws: actively writing
// after
async function runQuiet(fn, tries = 10) {
  for (let i = 0; i < tries; i++) {
    try { return await fn(); }
    catch (e) {
      if (!/actively writing/.test(e.message)) throw e;
      await new Promise(r => setTimeout(r, 3000));
    }
  }
  throw new Error('Trae DB never quiet');
}
runQuiet(() => traeSoloCli.config.set(k, v));
Defensive patterns

Strategy: retry

Validate before calling

import fs from 'fs';
const wal = TRAE_DB_WAL;
if (fs.existsSync(wal)) {
  const age = Date.now() - fs.statSync(wal).mtimeMs;
  if (age < 5000) throw new Error(`Trae DB busy (touched ${age}ms ago); wait and retry.`);
}

Try / catch

try {
  await mutateCmd();
} catch (e) {
  if (/actively writing/.test(e.message)) {
    await new Promise(r => setTimeout(r, 6000));
    return mutateCmd(); // single retry after settling
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling a state-mutating command while the Trae SOLO app is running and has written to database.db-wal less than windowSec seconds ago.

Common situations: Automating Trae SOLO while the desktop app is left open and syncing; running several CLI invocations back-to-back so the WAL keeps being touched; a background Trae process (indexing/sync) writing continuously.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/0e05dd5f198c566a. Report an issue: GitHub.