{"record":{"id":"778ba0e1f3ed7dca","repo":"jlcodes99/cockpit-tools","slug":"traeautocheckin","errorCode":null,"errorMessage":"[TraeAutoCheckin] 保存配置失败:","messagePattern":"\\[TraeAutoCheckin\\] 保存配置失败:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/services/traeAutoCheckinService.ts","lineNumber":64,"sourceCode":"      enabled: typeof parsed.enabled === 'boolean' ? parsed.enabled : false,\n      startTime: isValidTime(parsed.startTime) ? parsed.startTime : '06:00',\n      endTime: isValidTime(parsed.endTime) ? parsed.endTime : '12:00',\n      lastCheckedDate: typeof parsed.lastCheckedDate === 'string' ? parsed.lastCheckedDate : undefined,\n    };\n  } catch {\n    return DEFAULT_TRAE_AUTO_CHECKIN_CONFIG;\n  }\n}\n\nexport function saveTraeAutoCheckinConfig(config: TraeAutoCheckinConfig): void {\n  if (typeof window === 'undefined') {\n    return;\n  }\n  try {\n    localStorage.setItem(CONFIG_KEY, JSON.stringify(config));\n    window.dispatchEvent(new Event(TRAE_AUTO_CHECKIN_CONFIG_CHANGED_EVENT));\n  } catch (err) {\n    console.warn('[TraeAutoCheckin] 保存配置失败:', err);\n  }\n}\n\nexport function parseTimeToMinutes(timeStr: string): number {\n  const parts = timeStr.split(':').map(Number);\n  const h = parts[0] ?? 0;\n  const m = parts[1] ?? 0;\n  return h * 60 + m;\n}\n\nexport function getTodayDateString(): string {\n  const now = new Date();\n  const pad = (n: number) => String(n).padStart(2, '0');\n  return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;\n}\n\nexport function formatTimeOnly(date: Date = new Date()): string {\n  const pad = (n: number) => String(n).padStart(2, '0');","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/services/traeAutoCheckinService.ts#L46-L82","documentation":"saveTraeAutoCheckinConfig in src/services/traeAutoCheckinService.ts:64 persists the auto-checkin config via localStorage.setItem(CONFIG_KEY, JSON.stringify(config)). If that throws (or the preceding dispatch fails), it warns '[TraeAutoCheckin] 保存配置失败:' with the error and returns silently — the in-memory config change is not persisted, so it will be lost on reload.","triggerScenarios":"Calling saveTraeAutoCheckinConfig when localStorage write throws: storage quota exceeded, browser privacy/incognito mode blocking storage, localStorage disabled, or the page is in a sandboxed iframe with storage partitioning restrictions.","commonSituations":"Browser in private browsing with storage disabled; quota full from other large keys; embedded webview with disabled DOM storage; serialization of the config failing due to a non-JSON-safe value (circular structure) added to config.","solutions":["Open devtools and run localStorage.setItem manually to confirm whether storage writes work at all; exit private mode or enable storage.","Clear old localStorage entries to free quota if a QuotaExceededError was logged.","Validate the config object is JSON-serializable (no circular references or functions) before setItem.","Add a user-visible notification or in-memory fallback so a failed save is not silently lost on reload."],"exampleFix":"// before\n} catch (err) {\n  console.warn('[TraeAutoCheckin] 保存配置失败:', err);\n}\n// after\n} catch (err) {\n  console.warn('[TraeAutoCheckin] 保存配置失败:', err);\n  window.alert('自动签到配置保存失败，请检查浏览器存储设置');\n}","handlingStrategy":"try-catch","validationCode":"// Verify storage is writable before saving:\ntry {\n  localStorage.setItem('__probe__', '1');\n  localStorage.removeItem('__probe__');\n} catch {\n  console.warn('localStorage unavailable; config cannot be saved');\n}","typeGuard":"function canPersistToLocalStorage(): boolean {\n  try { localStorage.setItem('__t', '1'); localStorage.removeItem('__t'); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  localStorage.setItem(CONFIG_KEY, JSON.stringify(config));\n} catch (err) {\n  console.warn('[TraeAutoCheckin] 保存配置失败:', err);\n  keepInMemoryFallbackConfig(config); // survive until storage works\n}","preventionTips":["Check storage availability (private mode, quota) before relying on persistence.","Keep the config object JSON-safe — no circular refs or functions.","Notify the user when a save silently fails instead of only console.warn."],"tags":["typescript","localstorage","persistence","browser-storage"],"backgroundTag":"localstorage-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"}