{"record":{"id":"0e90e5bf402e65f6","repo":"thedotmack/claude-mem","slug":"vacuum-into-failed-falling-back-to-copyfilesync","errorCode":null,"errorMessage":"VACUUM INTO failed, falling back to copyFileSync","messagePattern":"VACUUM INTO failed, falling back to copyFileSync","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/services/infrastructure/CleanupV12_4_3.ts","lineNumber":182,"sourceCode":"        return;\n      }\n    }\n  }\n\n  const effectiveBackupsDir = path.join(effectiveDataDir, 'backups');\n  mkdirSync(effectiveBackupsDir, { recursive: true });\n  const ts = new Date().toISOString().replace(/[:.]/g, '-');\n  backupPath = path.join(effectiveBackupsDir, `claude-mem-pre-12.4.3-${ts}.db`);\n\n  const backupDb = new Database(dbPath, { readonly: true });\n  let vacuumFailed = false;\n  try {\n    backupDb.run(`VACUUM INTO '${backupPath.replace(/'/g, \"''\")}'`);\n    logger.info('SYSTEM', 'v12.4.3 backup created via VACUUM INTO', { backupPath, dbSize });\n  } catch (err: unknown) {\n    vacuumFailed = true;\n    const vacuumError = err instanceof Error ? err : new Error(String(err));\n    logger.warn('SYSTEM', 'VACUUM INTO failed, falling back to copyFileSync', {}, vacuumError);\n  }\n  backupDb.close();\n\n  if (vacuumFailed) {\n    try {\n      copyFileSync(dbPath, backupPath);\n      const walPath = `${dbPath}-wal`;\n      const shmPath = `${dbPath}-shm`;\n      if (existsSync(walPath)) copyFileSync(walPath, `${backupPath}-wal`);\n      if (existsSync(shmPath)) copyFileSync(shmPath, `${backupPath}-shm`);\n      logger.info('SYSTEM', 'v12.4.3 backup created via copyFileSync (incl. -wal/-shm if present)', { backupPath, dbSize });\n    } catch (copyErr: unknown) {\n      const copyError = copyErr instanceof Error ? copyErr : new Error(String(copyErr));\n      logger.error('SYSTEM', 'v12.4.3 backup failed via both VACUUM INTO and copyFileSync; aborting cleanup', {}, copyError);\n      return;\n    }\n  }\n","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/services/infrastructure/CleanupV12_4_3.ts#L164-L200","documentation":"The cleanup opens the DB read-only and runs SQLite's `VACUUM INTO '<backup>'` to produce a compact backup. If that statement fails, this warning is logged and the code falls back to raw copyFileSync of the db plus its -wal/-shm sidecars. Common failure causes: unwritable backups dir, insufficient disk space, SQLITE_BUSY from a concurrent writer, or a SQLite runtime older than 3.27 that lacks VACUUM INTO.","triggerScenarios":"backupDb.run(`VACUUM INTO ...`) throws: backups directory missing or read-only, disk full, SQLITE_BUSY because another connection holds a write lock, or the bundled SQLite predating VACUUM INTO support.","commonSituations":"Running cleanup while another claude-mem worker has the DB open for writing; permission-restricted backups directory; disk nearly full; an older runtime supplying SQLite 3.26 or earlier.","solutions":["Check the follow-up log line: if 'backup created via copyFileSync' appears, you already have a usable backup and only the compact form failed.","Free disk space so dbSize * 1.2 + 100 MB fits, then re-run to get the VACUUM form.","Stop other workers/clients holding the DB so VACUUM is not blocked (SQLITE_BUSY in the logged error).","Fix permissions on the backups directory; if VACUUM INTO keeps failing on an old SQLite runtime, upgrade the runtime or rely on the copy fallback."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// give VACUUM INTO its best chance: space, permissions, no writers\nassertWritableDir(backupsDir);\nassertFreeSpace(dataDir, statSync(dbPath).size * 1.2 + 100 * 1024 * 1024);\nawait stopOtherWorkers(); // release write locks","typeGuard":null,"tryCatchPattern":"try {\n  backupViaVacuumInto(db, backupPath);\n} catch (e) {\n  // compact backup failed — copyFileSync of db + -wal/-shm is the accepted equivalent\n  copyDbWithSidecars(dbPath, backupPath);\n}","preventionTips":["Stop competing workers before running cleanup so SQLITE_BUSY cannot abort the VACUUM.","Verify the backups directory is writable before upgrades.","Keep disk headroom of 1.2x DB size plus 100 MB."],"tags":["sqlite","backup","vacuum-into","disk-space"],"backgroundTag":"sqlite-vacuum-failed","analyzedSha":"e2d1df569a8f04075d40e92461128ece7cf04c82","analyzedAt":"2026-08-20T23:58:13.836Z","contentChangedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}