SubtitleEdit/subtitleedit · error · InvalidOperationException
Azure region is not set - enter it in the TTS engine setting
Error message
Azure region is not set - enter it in the TTS engine settings before refreshing voices.
What it means
InvalidOperationException thrown by DownloadAzureVoiceList before any network call when Se.Settings.Video.TextToSpeech.AzureRegion is blank. Azure's voice-list endpoint is region-specific ({region}.tts.speech.microsoft.com), so without a region the URL cannot even be constructed.
Source
Thrown at src/ui/Logic/Download/TtsDownloadService.cs:268
var error = (await result.Content.ReadAsStringAsync(cancellationToken)).Trim();
SeLogger.Error($"Murf TTS failed calling API address {url} : Status code={result.StatusCode} {TruncateForLog(error)}");
throw new HttpRequestException($"Murf voice list request failed: HTTP {(int)result.StatusCode} {result.StatusCode}");
}
await result.Content.CopyToAsync(ms, cancellationToken);
}
public async Task DownloadAzureVoiceList(Stream stream, IProgress<float>? progress, CancellationToken cancellationToken)
{
// Azure's official voice-list endpoint (the previous URL pointed at the ElevenLabs API,
// whose response Azure's parser cannot read). Requires the user's region + subscription
// key; the response is a JSON array with DisplayName/ShortName/Gender/Locale fields -
// the exact shape AzureSpeech.Map parses. Throws on failure so a refresh cannot
// overwrite the cached voice list with an error body.
var region = Se.Settings.Video.TextToSpeech.AzureRegion;
if (string.IsNullOrWhiteSpace(region))
{
throw new InvalidOperationException("Azure region is not set - enter it in the TTS engine settings before refreshing voices.");
}
var url = $"https://{region.Trim()}.tts.speech.microsoft.com/cognitiveservices/voices/list";
using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
requestMessage.Headers.TryAddWithoutValidation("Ocp-Apim-Subscription-Key", Se.Settings.Video.TextToSpeech.AzureApiKey.Trim());
var result = await _httpClient.SendAsync(requestMessage, cancellationToken);
result.EnsureSuccessStatusCode();
await result.Content.CopyToAsync(stream, cancellationToken);
}
public async Task<(bool Ok, string Error)> DownloadElevenLabsVoiceSpeak(
string inputText,
ElevenLabVoice voice,
string model,
string apiKey,
string languageCode,
MemoryStream stream,
IProgress<float>? progress,View on GitHub (pinned to 17a9f07487)
Solutions
- Open TTS engine settings and enter the Azure region (e.g. eastus, westeurope).
- Ensure the region matches the one the subscription key was provisioned in.
- Save settings and retry the voice refresh.
- If migrating settings, verify AzureRegion survived the migration.
Defensive patterns
Strategy: validation
Validate before calling
var region = Se.Settings.Video.TextToSpeech.AzureRegion;
if (string.IsNullOrWhiteSpace(region))
{
throw new InvalidOperationException("Set AzureRegion in TTS settings before refreshing voices.");
} Try / catch
try { await service.DownloadAzureVoiceList(stream, progress, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Azure region is not set"))
{ /* open TTS settings focused on the Azure region field */ } Prevention
- Validate AzureRegion in the UI before enabling the refresh button.
- Ensure AzureRegion survives settings migrations.
- Pair the region with the correct subscription key for that region.
When it happens
Trigger: string.IsNullOrWhiteSpace(region) is true at the top of DownloadAzureVoiceList; the throw happens before the request is built.
Common situations: User added an Azure API key but never set the region, or the settings migration cleared AzureRegion. The message directs the user to the TTS engine settings.
Related errors
- Qwen3 TTS (CrispASR) voice cloning requires a reference voic
- Qwen3 TTS (CrispASR) voice cloning needs the spoken transcri
- VibeVoice (CrispASR) requires a reference voice WAV. Import
- Color '{colorName}' not found in SKColors.
- Voice is not an AzureVoice
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/de8b0545b6a10eb0.
Report an issue: GitHub.