{"record":{"id":"5881e1be3b9c06b9","repo":"thedotmack/claude-mem","slug":"statfssync-failed-proceeding-without-disk-space-p","errorCode":null,"errorMessage":"statfsSync failed; proceeding without disk-space pre-flight","messagePattern":"statfsSync failed; proceeding without disk-space pre-flight","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/services/infrastructure/CleanupV12_4_3.ts","lineNumber":130,"sourceCode":"  logger.info('SYSTEM', 'v12.4.3 cleanup --dry-run scan complete', {\n    observerSessions: counts.observerSessions,\n    observerCascadeRows: counts.observerCascadeRows,\n    stuckPendingMessages: counts.stuckPendingMessages,\n  });\n  return counts;\n}\n\nfunction executeCleanup(dbPath: string, effectiveDataDir: string, markerPath: string): void {\n  const dbSize = statSync(dbPath).size;\n  const required = Math.ceil(dbSize * 1.2) + 100 * 1024 * 1024;\n\n  let backupPath: string | null = null;\n  let fsStats: ReturnType<typeof statfsSync> | undefined;\n  try {\n    fsStats = statfsSync(effectiveDataDir);\n  } catch (err: unknown) {\n    const error = err instanceof Error ? err : new Error(String(err));\n    logger.warn('SYSTEM', 'statfsSync failed; proceeding without disk-space pre-flight', {}, error);\n  }\n\n  if (fsStats) {\n    const bsize = Number(fsStats.bsize);\n    const bavail = Number(fsStats.bavail);\n\n    // Bun <= 1.3.14 on darwin-x64 returns a misaligned statfs struct\n    // (bsize = 0, fields shifted by one slot). Tracking issue:\n    //   https://github.com/oven-sh/bun/issues/31133\n    // Fix landed upstream in:\n    //   https://github.com/oven-sh/bun/pull/31139\n    // and will ship in the next Bun release after 1.3.14. Until then, any\n    // `bavail * bsize` math returns 0 and this gate would permanently skip\n    // the cleanup with a misleading `free=0` error. Treat non-credible\n    // readings (bsize <= 0, NaN, or non-finite) as \"skip the gate\" rather\n    // than \"disk is full\" -- a real out-of-space condition will still\n    // surface from the subsequent VACUUM INTO / copyFileSync.\n    if (!Number.isFinite(bsize) || !Number.isFinite(bavail) || bsize <= 0) {","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/services/infrastructure/CleanupV12_4_3.ts#L112-L148","documentation":"The v12.4.3 cleanup backs up the SQLite DB and first stats the target filesystem with statfsSync to confirm room for dbSize * 1.2 + 100 MB. If statfsSync throws, this warning is logged and the migration continues without the disk-space pre-flight. The backup still runs; only the early 'not enough space' abort is skipped, so a full disk now surfaces later as a VACUUM INTO or copyFileSync failure instead.","triggerScenarios":"statfsSync(effectiveDataDir) throws: the data directory does not exist yet, sits on an unmounted/unavailable network mount, lacks stat permissions, or the filesystem does not support statfs from the runtime.","commonSituations":"First run before the data dir is created; data dir on a disconnected NFS/SMB mount; FUSE or unusual filesystems; containerized runs with a misconfigured or missing volume mount for the data dir.","solutions":["Confirm the data directory exists and its mount is live before the cleanup/upgrade runs.","Read the logged error: ENOENT means the dir is missing, EACCES means permission trouble, EIO hints at a bad mount.","Manually verify free space (df on the data dir) covers dbSize * 1.2 + 100 MB, since the automatic pre-flight was skipped.","Fix the data dir configuration (env/config pointing at the wrong path), then re-run."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// replace the skipped pre-flight with your own space check before upgrading\nimport { statfsSync, existsSync, statSync } from 'node:fs';\n\nif (existsSync(dataDir)) {\n  const need = Math.ceil(statSync(dbPath).size * 1.2) + 100 * 1024 * 1024;\n  const fs = statfsSync(dataDir);\n  const free = Number(fs.bsize) * Number(fs.bavail);\n  if (free < need) throw new Error(`need ${need} bytes, only ${free} free`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run df on the data directory before any migration or backup step.","Ensure the data directory exists and its mount is healthy before starting the worker.","Keep at least 1.2x DB size + 100 MB free in the data partition."],"tags":["disk-space","filesystem","backup","pre-flight"],"backgroundTag":"disk-space-check-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"}