ChatGPTNextWeb/NextChat · error · Error

Could not infer voiceLocale from voiceName!

Error message

Could not infer voiceLocale from voiceName!

What it means

Thrown at app/utils/ms_edge_tts.ts:296 inside setMetadata when voiceLocale is not supplied and the voiceName fails to match VOICE_LANG_REGEX (=/\w{2}-\w{2}/). The regex extracts a locale like 'en-US' from a ShortName voice such as 'en-US-AriaNeural'; if the voiceName lacks that 'XX-XX' locale segment, inference fails and synthesis cannot proceed because the SSML xml:lang would be empty.

Source

Thrown at app/utils/ms_edge_tts.ts:296

   * @param voiceName a string with any `ShortName`. A list of all available neural voices can be found [here](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/language-support#neural-voices). However, it is not limited to neural voices: standard voices can also be used. A list of standard voices can be found [here](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/language-support#standard-voices)
   * @param outputFormat any {@link OUTPUT_FORMAT}
   * @param voiceLocale (optional) any voice locale that is supported by the voice. See the list of all voices for compatibility. If not provided, the locale will be inferred from the `voiceName`
   */
  async setMetadata(
    voiceName: string,
    outputFormat: OUTPUT_FORMAT,
    voiceLocale?: string,
  ) {
    const oldVoice = this._voice;
    const oldVoiceLocale = this._voiceLocale;
    const oldOutputFormat = this._outputFormat;

    this._voice = voiceName;
    this._voiceLocale = voiceLocale;
    if (!this._voiceLocale) {
      const voiceLangMatch = MsEdgeTTS.VOICE_LANG_REGEX.exec(this._voice);
      if (!voiceLangMatch)
        throw new Error("Could not infer voiceLocale from voiceName!");
      this._voiceLocale = voiceLangMatch[0];
    }
    this._outputFormat = outputFormat;

    const changed =
      oldVoice !== this._voice ||
      oldVoiceLocale !== this._voiceLocale ||
      oldOutputFormat !== this._outputFormat;

    // create new client
    if (changed || this._ws!.readyState !== this._ws!.OPEN) {
      this._startTime = Date.now();
      await this._initClient();
    }
  }

  private _metadataCheck() {
    if (!this._ws)

View on GitHub (pinned to defdcdb55d)

Solutions

  1. Always pass an official ShortName (e.g. 'en-US-AriaNeural') obtained from getVoices().
  2. Pass an explicit voiceLocale argument to setMetadata so inference is not relied upon.
  3. Validate voiceName against /\w{2}-\w{2}/ before calling setMetadata and warn the user early.
  4. If supporting non-ShortName voices, build a voiceName->locale lookup from the voices list and look it up instead of regex inference.

Example fix

// before
await tts.setMetadata('Aria', OUTPUT_FORMAT.AUDIO_24KHZ_48KBITRATE_MONO_MP3);

// after
const voiceName = 'en-US-AriaNeural';
await tts.setMetadata(
  voiceName,
  OUTPUT_FORMAT.AUDIO_24KHZ_48KBITRATE_MONO_MP3,
  'en-US', // explicit locale, no inference needed
);
Defensive patterns

Strategy: validation

Validate before calling

const VOICE_LOCALE_RE = /\w{2}-\w{2}/;

function canInferLocale(voiceName: string): boolean {
  return VOICE_LOCALE_RE.test(voiceName);
}

if (!canInferLocale(voiceName)) {
  throw new Error(
    `voiceName "${voiceName}" has no locale segment; pass an explicit voiceLocale`,
  );
}
await tts.setMetadata(voiceName, outputFormat);

Type guard

function isShortNameVoice(name: string): boolean {
  // ShortName format: <locale>-<VoiceName>Neural, e.g. en-US-AriaNeural
  return /^\w{2}-\w{2}-\w+Neural$/.test(name);
}

Try / catch

try {
  await tts.setMetadata(voiceName, outputFormat);
} catch (e) {
  if (e instanceof Error && /infer voiceLocale/.test(e.message)) {
    await tts.setMetadata(voiceName, outputFormat, "en-US"); // explicit fallback locale
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Passing a voiceName with no locale segment (e.g. 'Aria', 'MyCustomVoice', or a malformed/empty string); passing a voiceName with an uppercase country-only or language-only segment that does not match the two-letter-two-letter pattern; passing a LongName or multilingual voice id whose format differs from ShortName.

Common situations: Hard-coding a voice display name instead of its ShortName; user types a custom voice string in settings; voice list loaded from a different/older source whose names don't include the locale; passing undefined/'' accidentally.

Related errors


AI-assisted analysis of ChatGPTNextWeb/NextChat@defdcdb55d (2026-08-12). Data as JSON: /api/errors/681a47bdc1c84c9c. Report an issue: GitHub.