SubtitleEdit/subtitleedit · error · ArgumentException

Voice is not a AllTalkVoice

Error message

Voice is not a AllTalkVoice

What it means

AllTalk.Speak pattern-matches voice.EngineVoice to AllTalkVoice; any other engine's voice type triggers ArgumentException before any network call. This is a programmer/config error, not a transient failure — the wrong voice object reached the AllTalk engine.

Source

Thrown at src/ui/Features/Video/TextToSpeech/Engines/AllTalk.cs:161

    {
        var ms = new MemoryStream();
        await _ttsDownloadService.DownloadAllTalkVoiceList(ms, null, cancellationToken);
        await File.WriteAllBytesAsync(Path.Combine(GetSetAllTalkFolder(), JsonFileName), ms.ToArray(), cancellationToken);
        return await GetVoices(language);
    }

    public async Task<TtsResult> Speak(
        string text,
        string outputFolder,
        Voice voice,
        TtsLanguage? language,
        string? region,
        string? model,
        CancellationToken cancellationToken)
    {
        if (voice.EngineVoice is not AllTalkVoice allTalkVoice)
        {
            throw new ArgumentException("Voice is not a AllTalkVoice");
        }

        var languageCode = language != null ? language.Code : "en";
        Se.WriteToolsLog($"AllTalk: voice={allTalkVoice.Voice}, language={languageCode}, textLen={text.Length}");
        var allTalkFileNameOutputFileName = await _ttsDownloadService.AllTalkVoiceSpeak(text, allTalkVoice, languageCode, cancellationToken);

        // The server reports its output as a local path. It can be empty (unexpected response
        // JSON) or unreachable from here (server on another machine / different working dir) -
        // File.Move then threw unhandled instead of failing the segment like other engines.
        if (string.IsNullOrWhiteSpace(allTalkFileNameOutputFileName) || !File.Exists(allTalkFileNameOutputFileName))
        {
            var error = $"AllTalk did not produce a readable output file (reported path: \"{allTalkFileNameOutputFileName}\") - is the server running on this machine?";
            Se.WriteToolsLog("AllTalk: " + error, true);
            return new TtsResult { Text = text, FileName = string.Empty, Error = true, ErrorMessage = error };
        }

        var outputFileName = Path.Combine(TtsOutputFolder.Resolve(outputFolder, GetSetAllTalkFolder), Guid.NewGuid() + ".wav");
        File.Move(allTalkFileNameOutputFileName, outputFileName);

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Re-select the voice from the AllTalk voice list after switching to the AllTalk engine.
  2. Clear persisted voice mappings that reference other engines before invoking Speak.
  3. Filter the voice picker UI to voices owned by the active engine only.

Example fix

// before: pass any voice
await _allTalk.Speak(text, out, voice, lang, region, model, ct);
// after: guard at the call site
if (voice.EngineVoice is not AllTalkVoice)
    throw new InvalidOperationException($"Voice {voice.Name} is not an AllTalk voice; re-select it.");
await _allTalk.Speak(text, out, voice, lang, region, model, ct);
Defensive patterns

Strategy: type-guard

Validate before calling

if (voice.EngineVoice is not AllTalkVoice) return Invalid($"Voice {voice.Name} is not an AllTalk voice");

Type guard

static bool IsAllTalkVoice(Voice v) => v.EngineVoice is AllTalkVoice;

Try / catch

try { await allTalk.Speak(...); }
catch (ArgumentException ex) when (ex.Message.Contains("AllTalkVoice"))
{ /* re-select the voice from the AllTalk list */ }

Prevention

When it happens

Trigger: A Voice whose EngineVoice is not AllTalkVoice is passed to AllTalk.Speak (e.g. an AzureVoice or MorpheusVoice selected while the AllTalk engine is the active one).

Common situations: Stale voice mapping persisted after the user switched engines; deserialized Voice lost its typed EngineVoice; cast-dialog race where the voice list and the active engine disagree.

Related errors


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