{"record":{"id":"48118a6aed395764","repo":"danny-avila/LibreChat","slug":"multiple-providers-are-set-please-set-only-one-pr-48118a","errorCode":null,"errorMessage":"Multiple providers are set. Please set only one provider.","messagePattern":"Multiple providers are set\\. Please set only one provider\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"api/server/services/Files/Audio/TTSService.js","lineNumber":60,"sourceCode":"  /**\n   * Retrieves the configured TTS provider.\n   * @param {AppConfig | null | undefined} [appConfig] - The app configuration object.\n   * @returns {string} The name of the configured provider.\n   * @throws {Error} If no provider is set or multiple providers are set.\n   */\n  getProvider(appConfig) {\n    const ttsSchema = appConfig?.speech?.tts;\n    if (!ttsSchema) {\n      throw new Error(\n        'No TTS schema is set. Did you configure TTS in the custom config (librechat.yaml)?',\n      );\n    }\n    const providers = Object.entries(ttsSchema).filter(\n      ([key, value]) => key !== 'allowedAddresses' && Object.keys(value).length > 0,\n    );\n\n    if (providers.length !== 1) {\n      throw new Error(\n        providers.length > 1\n          ? 'Multiple providers are set. Please set only one provider.'\n          : 'No provider is set. Please set a provider.',\n      );\n    }\n    return providers[0][0];\n  }\n\n  /**\n   * Selects a voice for TTS based on provider schema and request.\n   * @async\n   * @param {Object} providerSchema - The schema for the selected provider.\n   * @param {string} requestVoice - The requested voice.\n   * @returns {Promise<string>} The selected voice.\n   */\n  async getVoice(providerSchema, requestVoice) {\n    const voices = providerSchema.voices.filter((voice) => voice && voice.toUpperCase() !== 'ALL');\n    let voice = requestVoice;","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/server/services/Files/Audio/TTSService.js#L42-L78","documentation":"getProvider filters ttsSchema entries (excluding `allowedAddresses`) for non-empty objects and requires exactly one. If two or more providers are populated (e.g. openai AND elevenlabs), it throws because it cannot pick.","triggerScenarios":"librechat.yaml `speech.tts` has more than one provider block populated with at least one field each.","commonSituations":"Example config pasted with two providers; switched providers without removing the old block; default + override both populated.","solutions":["Keep only one populated provider under speech.tts; empty or remove the rest.","Reload the config / restart the API server."],"exampleFix":"# before\nspeech:\n  tts:\n    openai: { apiKey: '...' }\n    elevenlabs: { apiKey: '...' }\n\n# after\nspeech:\n  tts:\n    elevenlabs: { apiKey: '...', voices: ['...'] }","handlingStrategy":"validation","validationCode":"const providers = Object.entries(appConfig.speech.tts || {})\n  .filter(([k, v]) => k !== 'allowedAddresses' && v && Object.keys(v).length > 0);\nif (providers.length > 1) {\n  throw new Error(`Multiple TTS providers configured: ${providers.map(p => p[0]).join(', ')}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep exactly one TTS provider block populated.","Add a CI lint that fails when more than one TTS provider is non-empty.","Document the single-provider constraint by the speech.tts example."],"tags":["tts","config","misconfiguration","provider"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}