{"record":{"id":"600bfc3284b25dca","repo":"moeru-ai/airi","slug":"speech-pipeline-openai-compatible-no-voice-in-p","errorCode":null,"errorMessage":"[Speech Pipeline] OpenAI Compatible: No voice in provider config, using default","messagePattern":"\\[Speech Pipeline\\] OpenAI Compatible: No voice in provider config, using default","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/stage-ui/src/components/scenes/Stage.vue","lineNumber":500,"sourceCode":"          description: providerConfig.voice as string,\n          previewURL: '',\n          languages: [{ code: 'en', title: 'English' }],\n          provider: activeSpeechProvider.value,\n          gender: 'neutral',\n        }\n      }\n      else {\n        // Fallback to default if not in provider config\n        voice = {\n          id: 'alloy',\n          name: 'alloy',\n          description: 'alloy',\n          previewURL: '',\n          languages: [{ code: 'en', title: 'English' }],\n          provider: activeSpeechProvider.value,\n          gender: 'neutral',\n        }\n        console.warn('[Speech Pipeline] OpenAI Compatible: No voice in provider config, using default', { providerConfig })\n      }\n    }\n\n    if (!model || !voice)\n      return null\n\n    try {\n      const speechRequest = speechStore.resolveSpeechInput({\n        text: request.text,\n        voice,\n        providerConfig: {\n          ...providerConfig,\n          pitch: ssmlEnabled.value ? pitch.value : undefined,\n        },\n        forceSSML: ssmlEnabled.value,\n        supportsSSML: speechStore.supportsSSML,\n      })\n","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui/src/components/scenes/Stage.vue#L482-L518","documentation":"For the openai-compatible-audio-speech provider, Stage.vue builds the voice object from providerConfig.voice. When it is unset, it synthesizes a default 'alloy' voice record (id/name 'alloy') and warns. On non-OpenAI endpoints without an 'alloy' voice the later synthesis call fails at the API level.","triggerScenarios":"The openai-compatible-audio-speech provider was saved without a voice field while TTS is requested.","commonSituations":"Provider configured with only API key, base URL and model; voice selection skipped during setup; config persisted by an older app version.","solutions":["Open Settings > Providers > openai-compatible-audio-speech, set the voice field to a voice your endpoint serves, and save","Fetch the provider's voice list (API key + base URL configured) and select one explicitly","If the default is intended, confirm the endpoint actually supports the 'alloy' voice"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before enabling TTS for openai-compatible-audio-speech\nconst config = providers.value['openai-compatible-audio-speech']\nif (!config?.voice) {\n  // mark provider incomplete in settings UI instead of relying on the alloy default\n  console.warn('[Speech Pipeline] OpenAI Compatible: No voice in provider config, using default')\n}","typeGuard":"function hasProviderVoice(config: unknown): config is { voice: string } {\n  return Boolean(config) && typeof config === 'object' && typeof (config as any).voice === 'string' && (config as any).voice.length > 0\n}","tryCatchPattern":null,"preventionTips":["Make voice a required field in the openai-compatible-audio-speech settings form","Select a voice from the endpoint's fetched voice list rather than assuming 'alloy' exists","Treat the warn as incomplete setup, not a working default"],"tags":["speech","tts","openai-compatible","provider-config","default-fallback"],"backgroundTag":"missing-voice-in-provider-config","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}