SubtitleEdit/subtitleedit · error · Exception
DeepLXTranslate gave empty alternatives: StatusCode={result.
Error message
DeepLXTranslate gave empty alternatives: StatusCode={result.StatusCode}
{resultContent} What it means
Thrown by DeepLXTranslate when the HTTP response was 2xx (success) but the JSON body contains neither an 'alternatives' array element nor a 'data' field usable as the translated text. Indicates a schema/protocol drift between this client and the DeepLX version, or an empty result DeepLX returned without erroring.
Source
Thrown at src/libuilogic/AutoTranslate/DeepLXTranslate.cs:102
if (string.IsNullOrEmpty(data))
{
var dataValues = parser.GetAllTagsByNameAsStrings(resultContent, "data");
if (dataValues.Count > 0)
{
data = dataValues[0];
}
}
if (!string.IsNullOrEmpty(data))
{
var resultText = Json.DecodeJsonText(data);
var resultTextWithFixedNewLines = ChatGptTranslate.FixNewLines(resultText);
return resultTextWithFixedNewLines.Trim();
}
SeLogger.Error("DeepLXTranslate.Translate: " + resultContent);
throw new Exception("DeepLXTranslate gave empty alternatives: StatusCode=" + result.StatusCode + Environment.NewLine + resultContent);
}
catch (Exception ex)
{
SeLogger.Error(ex, "DeepLXTranslate.Translate: " + ex.Message + Environment.NewLine + resultContent);
throw;
}
}
private static StringContent MakeContent(string text, string sourceLanguageCode, string targetLanguageCode)
{
var input = "{ \"source_lang\": \"" + sourceLanguageCode + "\", \"target_lang\": \"" + targetLanguageCode + "\", \"text\": \"" + Json.EncodeJsonText(text.Trim(), "\\n") + "\" }";
var content = new StringContent(input, Encoding.UTF8);
return content;
}
public void Dispose()
{
_httpClient?.Dispose();View on GitHub (pinned to 17a9f07487)
Solutions
- Log/capture the raw resultContent to see what DeepLX actually returned.
- Pin the DeepLX version to one matching this client's parser, or update SubtitleEdit.
- Test the same language pair directly against DeepLX with curl to isolate the schema issue.
- Try a well-supported language pair (e.g. en -> de) to rule out pair-specific emptiness.
Example fix
// before
SeLogger.Error("DeepLXTranslate.Translate: " + resultContent);
throw new Exception("DeepLXTranslate gave empty alternatives: StatusCode=" + result.StatusCode + Environment.NewLine + resultContent);
// after - keep the raw body for diagnosis and hint at version mismatch
SeLogger.Error("DeepLXTranslate.Translate: empty result body was: " + resultContent);
throw new Exception("DeepLXTranslate returned no translatable text (possible version/schema mismatch with DeepLX). StatusCode=" + result.StatusCode + Environment.NewLine + resultContent); Defensive patterns
Strategy: fallback
Validate before calling
// Before trusting the DeepLX response, sanity-check it parses as JSON with expected keys
try
{
var jo = Newtonsoft.Json.Linq.JObject.Parse(resultContent);
if (jo["alternatives"] == null && jo["data"] == null)
throw new InvalidOperationException("DeepLX response has no 'alternatives' or 'data' key - possible version mismatch.");
}
catch (Newtonsoft.Json.JsonReaderException)
{
throw new InvalidOperationException("DeepLX did not return valid JSON.");
} Type guard
public static bool HasDeepLXResultField(string body)
=> body.Contains("\"alternatives\"") || body.Contains("\"data\""); Try / catch
try
{
return await deepLX.Translate(text, src, tgt, token);
}
catch (Exception ex) when (ex.Message.Contains("empty alternatives"))
{
// Fall back to another translator or surface a version-mismatch hint
throw new InvalidOperationException("DeepLX returned no text - its response schema may differ from the expected version.", ex);
} Prevention
- Pin the DeepLX version; test after upgrades since the schema can change.
- Pre-test an en->de translation to confirm the response shape before batch use.
- Capture raw response bodies during development to detect schema drift early.
- Offer a fallback translator so a DeepLX schema change does not halt a run.
When it happens
Trigger: Translate() parses resultContent with SeJsonParser looking for 'alternatives' (GetArrayElementsByName) then falls back to 'data' (GetAllTagsByNameAsStrings); both come back empty/null, so execution reaches the throw at DeepLXTranslate.cs:102. Happens after a DeepLX version upgrade that changed its response schema, or when DeepLX returns an empty translation for unsupported language pairs.
Common situations: DeepLX upgraded to a version with a new response format; requesting a language pair DeepL/DeepLX does not support; DeepLX returned an empty alternatives list silently; mismatched DeepLX fork (the code targets github.com/OwO-Network/DeepLX).
Related errors
- {StaticName} returned an unexpected response: {responseStrin
- DeepLXTranslate error: StatusCode={result.StatusCode} {resul
- Could not parse response: {e.Message}
- Could not find matching AF_initDataCallback
- Invalid ASSA time code: {time}
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/d771a04cd5d6b742.
Report an issue: GitHub.