SubtitleEdit/subtitleedit · error · Exception

Translation engine {translator.Name} returned no translation

Error message

Translation engine {translator.Name} returned no translation for line {index + 1} after {noProgressCount} attempts

What it means

Thrown when a translation engine (MergeAndTranslateIfPossible via a translator) returns zero translated lines for the same subtitle line more than 3 consecutive times without throwing an exception. This is an anti-infinite-loop guard: without it, the outer while loop would retry the same line forever because translateCount stays 0 and index never advances.

Source

Thrown at src/ui/Features/Translate/AutoTranslateViewModel.cs:1605

                    });

                    if (_onlyCurrentLine)
                    {
                        _translationProgressIndex = index - 1;
                        Dispatcher.UIThread.Invoke(() => IsTranslateEnabled = true);
                        break;
                    }
                }
                else
                {
                    forceSingleLineMode = true;

                    // The engine keeps returning nothing for this line without throwing -
                    // without a cap the loop would retry the same line forever.
                    noProgressCount++;
                    if (noProgressCount > 3)
                    {
                        throw new Exception($"Translation engine {translator.Name} returned no translation for line {index + 1} after {noProgressCount} attempts");
                    }
                }
            }

        }
        catch (OperationCanceledException) when (_abort || _cancellationTokenSource.IsCancellationRequested)
        {
            // User pressed Cancel — let the finally block report it; do not surface as an error.
            // Check both _abort and the token: Cancel() sets _abort then fires the token, but the
            // worker thread can observe cancellation before _abort is visible across threads.
        }
        catch (Exception ex)
        {
            _ = Dispatcher.UIThread.Invoke(async () =>
            {
                var details = new System.Text.StringBuilder();

                // Lead with the endpoint actually used - reports often only show the error

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Inspect the specific line {index+1} in the subtitle file for degenerate content (empty, special chars only, pure formatting tags) and edit or skip it.
  2. Switch to a different translation engine or model that handles the problematic line.
  3. Enable forceSingleLineMode permanently for the batch to reduce context/parsing complexity.
  4. Check the translator engine's logs for empty API responses or parsing failures on that line.
  5. Increase the retry cap if the engine is intermittently returning empty (though this just delays the throw).

Example fix

// before
noProgressCount++;
if (noProgressCount > 3)
{
    throw new Exception($"Translation engine {translator.Name} returned no translation for line {index + 1} after {noProgressCount} attempts");
}

// after — skip the degenerate line with a warning instead of aborting the whole batch
noProgressCount++;
if (noProgressCount > 3)
{
    ApplyRowUpdateOnUiThread(index, $"[SKIPPED] {Rows[index].Original.Text}");
    SeLogger.LogWarning($"{translator.Name} returned no translation for line {index + 1} after {noProgressCount} attempts; skipping.");
    index++;
    noProgressCount = 0;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: skip empty or degenerate lines before calling the translator
var lineText = Rows[index].Original.Text?.Trim();
if (string.IsNullOrWhiteSpace(lineText) ||
    lineText.All(c => "♪#§~_-".Contains(c)))
{
    index++;
    continue;
}

Try / catch

try { /* translation loop */ }
catch (Exception ex) when (ex.Message.Contains("returned no translation"))
{ /* log, skip to next line or switch translator engine, resume batch */ }

Prevention

When it happens

Trigger: The translator engine (any ITranslator implementation) returns translateCount == 0 on every attempt for a specific line index. This occurs when the engine's API responds with an empty or unparseable result body that doesn't throw, or the source line is empty/degenerate. The counter increments per failed attempt and throws at attempt 4 (noProgressCount > 3).

Common situations: An LLM-based translator returns empty text for a line containing only special characters or formatting tags; the translation API rate-limits and returns empty 200 responses instead of errors; a model produces output that fails the engine's parsing/validation so zero lines are counted; the source line is a single character or punctuation that the model considers untranslatable.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/ea8e0977482d8c31. Report an issue: GitHub.