{"record":{"id":"104d26a6093dea44","repo":"jlcodes99/cockpit-tools","slug":"autobackup","errorCode":null,"errorMessage":"[AutoBackup] 定期备份执行失败:","messagePattern":"\\[AutoBackup\\] 定期备份执行失败:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/App.tsx","lineNumber":2252,"sourceCode":"    void syncWakeupStateOnStartup();\n  }, []);\n\n  useEffect(() => {\n    const AUTO_BACKUP_STARTUP_DELAY_MS = 5 * 60 * 1000;\n    const AUTO_BACKUP_POLL_INTERVAL_MS = 60 * 60 * 1000;\n    let startupTimerId: number | undefined;\n    let intervalId: number | undefined;\n    let inFlight = false;\n\n    const checkAutoBackup = async () => {\n      if (inFlight) {\n        return;\n      }\n      inFlight = true;\n      try {\n        await runAutoBackupCycle();\n      } catch (error) {\n        console.warn('[AutoBackup] 定期备份执行失败:', error);\n      } finally {\n        inFlight = false;\n      }\n    };\n\n    startupTimerId = window.setTimeout(() => {\n      void checkAutoBackup();\n      intervalId = window.setInterval(() => {\n        void checkAutoBackup();\n      }, AUTO_BACKUP_POLL_INTERVAL_MS);\n    }, AUTO_BACKUP_STARTUP_DELAY_MS);\n\n    return () => {\n      if (startupTimerId !== undefined) {\n        window.clearTimeout(startupTimerId);\n      }\n      if (intervalId !== undefined) {\n        window.clearInterval(intervalId);","sourceCodeStart":2234,"sourceCodeEnd":2270,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/App.tsx#L2234-L2270","documentation":"The periodic auto-backup timer invokes runAutoBackupCycle inside a guarded (inFlight) block; any rejection is logged with this warning and swallowed so the timer keeps running. It means a scheduled backup did not complete and on-disk backups may be stale until the next cycle succeeds.","triggerScenarios":"runAutoBackupCycle() throws: target backup directory missing or unwritable, disk full, backend backup command (Tauri IPC) fails, source data files locked, or backup config (interval/path) is invalid.","commonSituations":"User moved/deleted the backup directory; external drive disconnected; full disk; backend command signature changed after an app update.","solutions":["Read the logged error to distinguish IO (permission/path) from IPC errors","Verify the configured backup path exists and is writable; recreate it or prompt the user to pick a new one","Run one backup cycle manually to reproduce and capture the full error","Check available disk space and that no other process locks the target files"],"exampleFix":"// before\nawait runAutoBackupCycle();\n// after\nawait runAutoBackupCycle().catch((error) => {\n  console.warn('[AutoBackup] 定期备份执行失败:', error);\n  markBackupNeedsRetry();\n});","handlingStrategy":"retry","validationCode":"async function canWriteBackupDir(dir: string): Promise<boolean> {\n  try {\n    await writeTextFile(`${dir}/.write-test`, 'ok');\n    await remove(`${dir}/.write-test`);\n    return true;\n  } catch {\n    return false;\n  }\n}","typeGuard":"function isBackupConfig(v: unknown): v is { backupDir: string; intervalMs: number } {\n  return isPlainObject(v) && typeof v.backupDir === 'string' && v.backupDir.length > 0 && typeof v.intervalMs === 'number';\n}","tryCatchPattern":"inFlight = true;\ntry {\n  await runAutoBackupCycle();\n} catch (error) {\n  console.warn('[AutoBackup] 定期备份执行失败:', error);\n  scheduleBackupRetry();\n} finally {\n  inFlight = false;\n}","preventionTips":["Verify the backup directory exists and is writable on startup","Check disk space before running a cycle","Surface backup failures in the UI, not just the console","Keep the inFlight guard so overlapping cycles don't collide"],"tags":["backup","filesystem","scheduled-task"],"backgroundTag":"backup-write-failed","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}