{"record":{"id":"ed7359d4a523ac39","repo":"tonhowtf/omniget","slug":"subtitle-grammar-fix-error-surfaced-to-user-via-err","errorCode":null,"errorMessage":"subtitle_grammar_fix error surfaced to user via err() (localized toast)","messagePattern":"subtitle_grammar_fix error surfaced to user via err\\(\\) \\(localized toast\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/components/downloads/SubtitleWorkshop.svelte","lineNumber":179,"sourceCode":"      showToast(\"success\", $t(\"downloads.sw.translated\") as string);\n    } catch (e) {\n      err(e);\n    } finally {\n      busy = false;\n    }\n  }\n\n  async function grammarFix() {\n    if (!cues.length || busy) return;\n    busy = true;\n    try {\n      cues = await invoke<Cue[]>(\"subtitle_grammar_fix\", {\n        cues,\n        style: grammarStyle,\n      });\n      showToast(\"success\", $t(\"downloads.sw.grammar_done\") as string);\n    } catch (e) {\n      err(e);\n    } finally {\n      busy = false;\n    }\n  }\n\n  function autoFix() {\n    if (!cues.length) return;\n    const MIN_MS = 700;\n    const MAX_LINE = 42;\n    let changes = 0;\n\n    let next = cues\n      .filter((c) => c.text.trim().length > 0)\n      .map((c) => ({ ...c, text: c.text.trim() }))\n      .sort((a, b) => a.start_ms - b.start_ms);\n    if (next.length !== cues.length) changes += cues.length - next.length;\n\n    for (let i = 0; i < next.length; i++) {","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src/components/downloads/SubtitleWorkshop.svelte#L161-L197","documentation":"grammarFix failed while invoking subtitle_grammar_fix to apply AI grammar correction to the cues with the chosen style; err() surfaces the error as a localized toast and cues are left unchanged. Backend 'ai_not_configured' is mapped to the not-configured message by err().","triggerScenarios":"invoke('subtitle_grammar_fix',{cues,style:grammarStyle}) rejecting — AI provider unconfigured (ai_not_configured), unsupported grammar style value, upstream AI API failure, or invalid cues payload.","commonSituations":"Missing AI configuration/key on the backend; selecting a grammar style the backend doesn't recognize; AI service outage/quota limits; very long subtitle files timing out the AI request.","solutions":["If the toast indicates not-configured, set up the AI provider/key in backend configuration.","Confirm grammarStyle matches one of the backend's supported style values.","Check upstream AI service health/limits if the error points at the request itself.","Retry after transient failures; consider chunking large cue lists."],"exampleFix":"// before\nawait invoke(\"subtitle_grammar_fix\", { cues, style: grammarStyle });\n// after\nif (!aiConfigured()) { showToast(\"error\", $t(\"downloads.sw.not_configured\")); return; }\nawait invoke(\"subtitle_grammar_fix\", { cues, style: grammarStyle });","handlingStrategy":"validation","validationCode":"if (!(await invoke<boolean>(\"ai_configured\").catch(() => false))) { err(\"ai_not_configured\"); return; }\nconst styles = await invoke<string[]>(\"grammar_styles\").catch(() => []);\nif (!styles.includes(grammarStyle)) { showToast(\"error\", $t(\"downloads.sw.invalid_style\")); return; }","typeGuard":"function isSupportedStyle(v: unknown, allowed: readonly string[]): v is string {\n  return typeof v === \"string\" && allowed.includes(v);\n}","tryCatchPattern":"try {\n  cues = await invoke<Cue[]>(\"subtitle_grammar_fix\", { cues, style: grammarStyle });\n  showToast(\"success\", $t(\"downloads.sw.grammar_done\") as string);\n} catch (e) {\n  err(e); // localized toast\n} finally {\n  busy = false;\n}","preventionTips":["Gate grammar-fix UI on AI configuration status fetched at startup.","Derive grammarStyle options from the backend's supported list rather than hardcoding.","Add retry/backoff for transient AI provider failures.","Chunk long cue lists so a single oversized request can't fail the whole pass."],"tags":["tauri","invoke","grammar","ai"],"backgroundTag":"missing-api-key","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"}