{"record":{"id":"35de34dc72bfc09c","repo":"tonhowtf/omniget","slug":"subtitle-load-error-surfaced-to-user-via-err-localized-toast","errorCode":null,"errorMessage":"subtitle_load error surfaced to user via err() (localized toast)","messagePattern":"subtitle_load error surfaced to user via err\\(\\) \\(localized toast\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/components/downloads/SubtitleWorkshop.svelte","lineNumber":72,"sourceCode":"      (parseInt(m[1]) * 3600 + parseInt(m[2]) * 60 + parseInt(m[3])) * 1000 +\n      parseInt(m[4].padEnd(3, \"0\"))\n    );\n  }\n\n  async function loadFile() {\n    const sel = await openDialog({\n      multiple: false,\n      filters: [{ name: \"Subtitles\", extensions: [\"srt\", \"vtt\", \"ass\"] }],\n    });\n    if (!sel || typeof sel !== \"string\") return;\n    busy = true;\n    try {\n      cues = await invoke<Cue[]>(\"subtitle_load\", { path: sel });\n      loadedPath = sel;\n      peaks = [];\n      shots = [];\n    } catch (e) {\n      err(e);\n    } finally {\n      busy = false;\n    }\n  }\n\n  async function loadMedia() {\n    const sel = await openDialog({ multiple: false });\n    if (!sel || typeof sel !== \"string\") return;\n    busy = true;\n    try {\n      peaks = await invoke<number[]>(\"waveform_peaks\", { input: sel, buckets: 600 });\n      shots = await invoke<number[]>(\"detect_shot_changes\", { input: sel, threshold: 0.4 });\n    } catch (e) {\n      err(e);\n    } finally {\n      busy = false;\n    }\n  }","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src/components/downloads/SubtitleWorkshop.svelte#L54-L90","documentation":"SubtitleWorkshop's loadFile failed while invoking the Rust command subtitle_load for the selected subtitle path, and the raw error string is routed through err() to be shown as a localized toast. The workshop keeps previous cues; only the new file load failed.","triggerScenarios":"invoke('subtitle_load',{path:sel}) rejecting — file doesn't exist, unreadable, or the parser rejects the subtitle format/encoding (invalid SRT/ASS content).","commonSituations":"User picks a file that was moved/deleted after listing; non-UTF8 encodings; malformed subtitle files; path with characters the backend mishandles.","solutions":["Read the toast/err text: 'ai_not_configured' style raw codes are mapped, otherwise backend error strings are shown — identify file-not-found vs parse error.","Verify the path exists and is readable before invoking.","Try re-encoding the subtitle file to UTF-8.","Check the backend subtitle_load implementation for format limitations (e.g. only SRT supported)."],"exampleFix":"// before\n} catch (e) { err(e); }\n// after\n} catch (e) {\n  if (typeof e !== \"string\") err(\"invalid_subtitle_format\");\n  else err(e);\n}","handlingStrategy":"validation","validationCode":"const exists = await invoke<boolean>(\"path_exists\", { path: sel }).catch(() => false);\nif (!exists) { showToast(\"error\", $t(\"downloads.sw.file_missing\")); return; }","typeGuard":"function isSubtitlePath(v: unknown): v is string {\n  return typeof v === \"string\" && /\\.(srt|ass|vtt)$/i.test(v);\n}","tryCatchPattern":"try {\n  cues = await invoke<Cue[]>(\"subtitle_load\", { path: sel });\n} catch (e) {\n  err(e); // maps raw backend codes to localized toast messages\n} finally {\n  busy = false;\n}","preventionTips":["Verify the file still exists right before invoking (paths can go stale).","Restrict the file picker to supported subtitle extensions.","Convert non-UTF8 subtitles to UTF-8 before loading.","Keep err()'s raw-code mapping table in sync with backend error codes."],"tags":["tauri","invoke","subtitles","file-loading"],"backgroundTag":"file-read-failed","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}