{"record":{"id":"b263b6035fa47131","repo":"tonhowtf/omniget","slug":"omnidisc-could-not-read-cached-plaintext","errorCode":null,"errorMessage":"[omnidisc] could not read cached plaintext","messagePattern":"\\[omnidisc\\] could not read cached plaintext","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lib/stores/omnidisc-store.svelte.ts","lineNumber":2480,"sourceCode":"/// local cache in Rust. Anything it cannot recall stays honestly blank.\nexport async function hydrateEncrypted(channelId: string) {\n  const instance = instanceForChannel(channelId);\n  if (!instance || isDemo(instance.id)) return;\n  const waiting = (messagesByChannel[channelId] ?? [])\n    .filter((m) => m.awaitingDecryption && m.ciphertext)\n    .map((m) => m.ciphertext as string);\n  if (waiting.length === 0) return;\n  try {\n    const found = await invoke<Record<string, unknown>>(\"omnidisc_mls_recall\", {\n      url: instance.url,\n      ciphertexts: waiting,\n    });\n    for (const [ciphertext, raw] of Object.entries(found ?? {})) {\n      const payload = readPayload(raw);\n      if (payload) applyDecrypted(channelId, ciphertext, payload);\n    }\n  } catch (e) {\n    console.warn(\"[omnidisc] could not read cached plaintext\", errorText(e));\n  }\n}\n\nexport function getGroupStatus(channelId: string | null): OmnidiscGroupStatus | null {\n  return channelId ? (groupStatusByChannel[channelId] ?? null) : null;\n}\n\nexport async function refreshGroupStatus(channelId: string) {\n  const instance = instanceForChannel(channelId);\n  if (!instance || isDemo(instance.id) || !isEncryptedChannel(channelId)) return;\n  try {\n    const raw = await invoke<unknown>(\"omnidisc_mls_status\", { url: instance.url, channelId });\n    if (!isRecord(raw)) return;\n    const members = (Array.isArray(raw.members) ? raw.members : [])\n      .filter(isRecord)\n      .map((m) => ({\n        userId: str(m.user_id) ?? \"\",\n        deviceId: str(m.device_id) ?? \"\",","sourceCodeStart":2462,"sourceCodeEnd":2498,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src/lib/stores/omnidisc-store.svelte.ts#L2462-L2498","documentation":"hydrateEncrypted fetches cached decrypted message plaintext from the backend (a ciphertext→raw map) and applies each entry via applyDecrypted. If the backend read rejects or the map is unusable, the warning is logged and hydration silently fails — messages remain encrypted placeholders until a live `omnidisc://decrypted` event arrives.","triggerScenarios":"Calling hydrateEncrypted(channelId) when the backend command returning the cached plaintext map rejects: key store/decryption service unavailable, no cache entry for the channel, serialization mismatch on the returned map, or encrypted payloads that fail readPayload parsing.","commonSituations":"First device login with an empty local decryption cache; corrupted or rotated encryption keys; backend restarted and cache lost; schema change in the cached payload format after an app update so readPayload returns null for every entry.","solutions":["Check errorText(e) to distinguish backend read failure from empty cache","Verify the decryption keys for the channel exist/are loaded on this device","Confirm the cached payload format matches readPayload's expectations (version skew)","Fall back to live decryption: the hydrate path is optional since live decrypted events repopulate state"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// skip hydration when there is nothing cached to read\nif (!channelId || decryptedCount(channelId) > 0) return;\n","typeGuard":"function isPayloadMap(v: unknown): v is Record<string, unknown> {\n  return typeof v === \"object\" && v !== null;\n}\n","tryCatchPattern":"try {\n  const found = await invoke<Record<string, unknown>>(\"omnidisc_cached_plaintext\", { channelId });\n  for (const [ct, raw] of Object.entries(found ?? {})) {\n    const payload = readPayload(raw);\n    if (payload) applyDecrypted(channelId, ct, payload);\n  }\n} catch (e) {\n  console.warn(\"[omnidisc] could not read cached plaintext\", errorText(e));\n}","preventionTips":["Treat cached plaintext as an optimization; rely on live decrypted events as the source of truth","Validate cache entries with readPayload before applying","Version the cache payload format so schema changes invalidate rather than corrupt"],"tags":["svelte","encryption","cache","tauri"],"backgroundTag":"cache-read-failed","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}