tonhowtf/omniget · error

subtitle_translate error surfaced to user via err()…

Error message

subtitle_translate error surfaced to user via err() (localized toast)

What it means

translateAll failed while invoking subtitle_translate to machine-translate all cues to the target language; err() surfaces the backend error as a localized toast and cues are left unchanged. A raw 'ai_not_configured' code from the backend is specifically mapped to a 'not configured' message.

Solutions

  1. If the toast shows the not-configured message, configure the AI/translation provider and key in backend settings.
  2. Validate targetLang is a non-empty supported language code before invoking.
  3. Check upstream API status/limits if the error mentions request failure or rate limiting.
  4. Retry smaller batches of cues if payload size is the issue.

Example fix

// before
await invoke("subtitle_translate", { cues, targetLang: targetLang.trim() });
// after
const lang = targetLang.trim();
if (!lang) { showToast("error", $t("downloads.sw.enter_language")); return; }
await invoke("subtitle_translate", { cues, targetLang: lang });
Defensive patterns

Strategy: validation

Validate before calling

const lang = targetLang.trim();
if (!lang) { showToast("error", $t("downloads.sw.enter_language")); return; }
if (!(await invoke<boolean>("ai_configured").catch(() => false))) { err("ai_not_configured"); return; }

Type guard

function isValidTargetLang(v: unknown): v is string {
  return typeof v === "string" && /^[a-z]{2}(-[A-Z]{2})?$/.test(v.trim());
}

Try / catch

try {
  cues = await invoke<Cue[]>("subtitle_translate", { cues, targetLang: lang });
  showToast("success", $t("downloads.sw.translated") as string);
} catch (e) {
  err(e); // localized toast; maps ai_not_configured etc.
} finally {
  busy = false;
}

Prevention

When it happens

Trigger: invoke('subtitle_translate',{cues,targetLang}) rejecting — AI/translation backend not configured (ai_not_configured), empty/invalid targetLang, API failure upstream (rate limit, key invalid), or cues payload rejected.

Common situations: No AI provider/API key configured on the backend; empty or malformed target language string; translation service outage or quota exhaustion; extremely large subtitle files exceeding request limits.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/684b824ce08cdb93. Report an issue: GitHub.

Appendix: source

Thrown at src/components/downloads/SubtitleWorkshop.svelte:163

    if (i < cues.length - 1 && cues[i + 1].start_ms < c.end_ms)
      return $t("downloads.sw.qc_overlap") as string;
    const secs = (c.end_ms - c.start_ms) / 1000;
    const cps = secs > 0 ? c.text.replace(/\s/g, "").length / secs : 99;
    if (cps > 21) return $t("downloads.sw.qc_fast") as string;
    return null;
  }

  async function translateAll() {
    if (!targetLang.trim() || !cues.length || busy) return;
    busy = true;
    try {
      cues = await invoke<Cue[]>("subtitle_translate", {
        cues,
        targetLang: targetLang.trim(),
      });
      showToast("success", $t("downloads.sw.translated") as string);
    } catch (e) {
      err(e);
    } finally {
      busy = false;
    }
  }

  async function grammarFix() {
    if (!cues.length || busy) return;
    busy = true;
    try {
      cues = await invoke<Cue[]>("subtitle_grammar_fix", {
        cues,
        style: grammarStyle,
      });
      showToast("success", $t("downloads.sw.grammar_done") as string);
    } catch (e) {
      err(e);
    } finally {
      busy = false;

View on GitHub (pinned to 8600b91f42)