{"record":{"id":"bb63542c07f9f078","repo":"mastra-ai/mastra","slug":"not-enough-free-disk-space-to-compact-file-nee","errorCode":null,"errorMessage":"Not enough free disk space to compact ${file}: need ${formatBytes(requiredFreeBytes(liveBytes))} for a ${formatBytes(liveBytes)} compacted copy, but only ${formatBytes(freeBytes)} is free.","messagePattern":"Not enough free disk space to compact (.+?): need (.+?) for a (.+?) compacted copy, but only (.+?) is free\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/utils/storage-maintenance.ts","lineNumber":197,"sourceCode":"        `${file} is in use by another process — is another Mastra Code session running? ` +\n          `Close other sessions and run /prune vacuum again.`,\n      );\n    }\n    // Native `libsql` driver, not `@libsql/client`: the wrapper's close() can\n    // leave the file lock held in-process (cached statements), which would\n    // block other connections afterwards. This connection stays in rollback\n    // mode, so even a pinned statement holds no lock once we're done.\n    const db = new Database(file);\n    try {\n      db.exec('PRAGMA busy_timeout = 2000');\n      const pageSize = pragmaNumber(db, 'page_size');\n      const pageCount = pragmaNumber(db, 'page_count');\n      const freelistCount = pragmaNumber(db, 'freelist_count');\n      const liveBytes = Math.max(0, pageCount - freelistCount) * pageSize;\n      const { bsize, bavail } = statfsSync(dirname(file));\n      const freeBytes = bsize * bavail;\n      if (freeBytes < requiredFreeBytes(liveBytes)) {\n        throw new Error(\n          `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 });","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/utils/storage-maintenance.ts#L179-L215","documentation":"Before compacting, reclaimLibSQLDisk computes the live (non-freelist) bytes of the database and requires free disk space sufficient to hold a full compacted copy (VACUUM INTO writes a copy next to the file). If the filesystem's free space (statfsSync) is below that requirement, it aborts instead of risking a failed mid-write compaction.","triggerScenarios":"Running /prune vacuum on a storage file whose live bytes exceed the free space on the volume — e.g. a multi-GB db on a nearly full disk, or a small container volume / CI runner with tight disk quota.","commonSituations":"Docker volumes or CI machines with a few GB of free space hosting large thread/memory databases; log files or build artifacts filling the disk before a vacuum.","solutions":["Free disk space on the volume (delete build artifacts, logs, `docker system prune`) so at least requiredFreeBytes(liveBytes) is available","Move or prune large thread data first (smaller liveBytes reduces the needed space)","Run the vacuum on a machine/volume with sufficient free space, e.g. copy the project to a bigger disk"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { statfsSync, statSync } from 'node:fs';\nconst { bsize, bavail } = statfsSync(dirname(dbFile));\nconst freeBytes = bsize * bavail;\nconst liveBytes = statSync(dbFile).size; // rough upper bound of the compacted copy\nif (freeBytes < liveBytes * 1.2) throw new Error(`Need ~${liveBytes * 1.2} bytes free to compact; only ${freeBytes} free.`);","typeGuard":null,"tryCatchPattern":"try {\n  await maintenance.results();\n} catch (e) {\n  if (String(e.message).includes('Not enough free disk space')) {\n    console.error('Free up space or run the vacuum on a larger volume, then retry.');\n  } else throw e;\n}","preventionTips":["Monitor disk usage (`df -h`) before large vacuum operations","Prune old threads/data before vacuuming so liveBytes (and required space) shrink","Run vacuums on volumes with comfortable headroom, not near-full CI runners or containers"],"tags":["disk-space","sqlite","vacuum","filesystem"],"backgroundTag":"insufficient-disk-space","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}