{"record":{"id":"5922f5b20303e555","repo":"cjpais/Handy","slug":"failed-to-sync-theme-from-settings","errorCode":null,"errorMessage":"Failed to sync theme from settings:","messagePattern":"Failed to sync theme from settings:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lib/utils/theme.ts","lineNumber":61,"sourceCode":"export const getStoredTheme = (): Theme => {\n  try {\n    const stored = localStorage.getItem(THEME_STORAGE_KEY);\n    if (isTheme(stored)) return stored;\n  } catch {\n    // ignore\n  }\n  return \"system\";\n};\n\n/** Apply the persisted theme from AppSettings (the source of truth). */\nexport const syncThemeFromSettings = async (): Promise<void> => {\n  try {\n    const result = await commands.getAppSettings();\n    if (result.status === \"ok\") {\n      applyTheme(result.data.theme ?? \"system\");\n    }\n  } catch (e) {\n    console.warn(\"Failed to sync theme from settings:\", e);\n  }\n};\n","sourceCodeStart":43,"sourceCodeEnd":64,"githubUrl":"https://github.com/cjpais/Handy/blob/c89b7bf38974ad317177389f5bfe28236f0d64e3/src/lib/utils/theme.ts#L43-L64","documentation":"syncThemeFromSettings calls getAppSettings and applies result.data.theme ('light' | 'dark' | 'system') to the document. The ok-status path is handled and the error-status path is silently ignored; this catch only sees a rejected invoke (backend unreachable, command unregistered, store plugin not ready, browser context). The visible symptom is the app keeping the default/system appearance instead of the user's persisted choice.","triggerScenarios":"Calling syncThemeFromSettings before the Tauri backend/store plugin is ready; the getAppSettings command not registered; running the frontend in a plain browser where invoke rejects; a settings-store file that fails to parse so the command rejects rather than returning an error status.","commonSituations":"Startup ordering issues when the module runs at import time; plugin/capability misconfigurations; dev iteration in Vite; migrated or corrupted settings files after schema changes.","solutions":["Call syncThemeFromSettings after the app/window ready event or once onboarding completes, not only at module import","Verify the store plugin registration and capabilities include the settings command","Guard browser dev with isTauri()","Also handle result.status === \"error\" explicitly — an err status currently falls through with no log at all, which is the silent cousin of this warning"],"exampleFix":"// before\nconst result = await commands.getAppSettings();\nif (result.status === \"ok\") {\n  applyTheme(result.data.theme ?? \"system\");\n}\n\n// after\nconst result = await commands.getAppSettings();\nif (result.status === \"ok\") {\n  applyTheme(result.data.theme ?? \"system\");\n} else if (result.status === \"error\") {\n  console.warn(\"getAppSettings returned error, keeping default theme:\", result.error);\n}","handlingStrategy":"retry","validationCode":"import { isTauri } from \"@tauri-apps/api/core\";\nif (!isTauri()) return;","typeGuard":null,"tryCatchPattern":"try {\n  const result = await commands.getAppSettings();\n  if (result.status === \"ok\") applyTheme(result.data.theme ?? \"system\");\n  else console.warn(\"getAppSettings error status:\", result.error);\n} catch (e) { console.warn(\"Failed to sync theme from settings:\", e); }","preventionTips":["Run theme sync after ready, not only at module import","Handle both the err status and the rejected promise — the current code ignores one and warns the other","Guard browser dev with isTauri()"],"tags":["tauri","theme","settings","startup","invoke"],"backgroundTag":"tauri-command-invoke-failed","analyzedSha":"c89b7bf38974ad317177389f5bfe28236f0d64e3","analyzedAt":"2026-08-17T10:29:55.597Z","contentChangedAt":"2026-08-17T10:29:55.597Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}