{"record":{"id":"4dda85f634bd518f","repo":"mastra-ai/mastra","slug":"file-was-opened-by-another-process-during-compa","errorCode":null,"errorMessage":"${file} was opened by another process during compaction — is another Mastra Code session running? Close other sessions and run /prune vacuum again.","messagePattern":"(.+?) was opened by another process during compaction — is another Mastra Code session running\\? Close other sessions and run /prune vacuum again\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/utils/storage-maintenance.ts","lineNumber":216,"sourceCode":"          `Not enough free disk space to compact ${file}: need ${formatBytes(requiredFreeBytes(liveBytes))} ` +\n            `for a ${formatBytes(liveBytes)} compacted copy, but only ${formatBytes(freeBytes)} is free.`,\n        );\n      }\n      onFileStart?.(file, bytesBefore, liveBytes);\n      db.exec(`VACUUM INTO '${tmp.replace(/'/g, \"''\")}'`);\n    } catch (err) {\n      rmSync(tmp, { force: true });\n      throw err;\n    } finally {\n      db.close();\n    }\n    // Re-probe right before the swap: `VACUUM INTO` can take tens of seconds\n    // on multi-GB files, and a session started in that window reopens the db\n    // in WAL mode (flipping the header back). Swapping under it would orphan\n    // that session's inode and silently lose its writes.\n    if (journalModeFromHeader(file) !== 'delete') {\n      rmSync(tmp, { force: true });\n      throw new Error(\n        `${file} was opened by another process during compaction — is another Mastra Code session running? ` +\n          `Close other sessions and run /prune vacuum again.`,\n      );\n    }\n    // Swap the compacted copy into place. The old WAL/SHM sidecars belong to\n    // the old inode — they must never be paired with the new file. If any step\n    // after the first rename fails, restore the original so the db path is\n    // never left empty (a naive restart would otherwise create a fresh db).\n    renameSync(file, `${file}.old`);\n    try {\n      rmSync(`${file}-wal`, { force: true });\n      rmSync(`${file}-shm`, { force: true });\n      renameSync(tmp, file);\n    } catch (err) {\n      try {\n        renameSync(`${file}.old`, file);\n      } catch {\n        throw new Error(","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/utils/storage-maintenance.ts#L198-L234","documentation":"VACUUM INTO can take tens of seconds on large databases. After compaction finishes and before swapping the compacted copy into place, reclaimLibSQLDisk re-probes the journal-mode header. If it is no longer 'delete', a new session opened the database in WAL mode during the vacuum window; swapping under it would orphan that session's inode and silently lose its writes, so the tool deletes the temp copy and aborts.","triggerScenarios":"A Mastra Code session (or any libsql client) starts and opens the storage db in WAL mode while a long-running /prune vacuum is compacting it; the re-probe just before the rename detects the header flip.","commonSituations":"A teammate or a watcher (dev server, background agent) starts the app while you vacuum a multi-GB database; an auto-restart (nodemon, docker restart policy) respawns a session mid-vacuum.","solutions":["Re-run /prune vacuum with no other sessions able to start: stop dev servers, file watchers, and auto-restart policies","Repeat the vacuum — the aborted run cleaned up its temp file, no data was lost","Vacuum during a quiet window (e.g. before starting the TUI, in CI, or maintenance downtime)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import { readFileSync } from 'node:fs';\n// Re-check just before starting the vacuum that nothing else has the db open\nconst inWalMode = readFileSync(dbFile).subarray(18, 19).toString() === String.fromCharCode(2);\nif (inWalMode) throw new Error('Aborting: db opened in WAL mode by another process.');","typeGuard":null,"tryCatchPattern":"try {\n  await maintenance.results();\n} catch (e) {\n  if (String(e.message).includes('was opened by another process during compaction')) {\n    console.error('No data lost. Ensure no sessions can start (disable watchers/auto-restart), then re-run the vacuum.');\n  } else throw e;\n}","preventionTips":["Stop file watchers and auto-restart policies (nodemon, docker restart) before vacuuming multi-GB databases","Vacuum during maintenance windows or in CI where no other sessions can start","Keep databases small via regular pruning so the VACUUM window stays short"],"tags":["sqlite","concurrency","race-condition","vacuum"],"backgroundTag":"database-file-locked","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}