{"record":{"id":"af6f9720e53d6fb7","repo":"danny-avila/LibreChat","slug":"no-provider-is-set-please-set-a-provider-af6f97","errorCode":null,"errorMessage":"No provider is set. Please set a provider.","messagePattern":"No provider is set\\. Please set a provider\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","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":"The `speech.tts` block is present (passed the falsy check at line 51) but after filtering out `allowedAddresses` and empty objects, zero providers remain. Every provider entry is an empty object — e.g. `tts: { openai: {} }`.","triggerScenarios":"speech.tts is a non-falsy object whose only entries are `allowedAddresses` and/or provider keys mapped to empty objects.","commonSituations":"Placeholder config committed without values; subfields commented out leaving `{}`; YAML indentation producing an empty mapping.","solutions":["Populate at least one provider with required fields (e.g. openai.apiKey + model, or elevenlabs.apiKey + voices).","Reload the config / restart the API server."],"exampleFix":"# before\nspeech:\n  tts:\n    elevenlabs: {}\n\n# after\nspeech:\n  tts:\n    elevenlabs:\n      apiKey: '${TTS_API_KEY}'\n      model: 'eleven_multilingual_v2'\n      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 === 0) {\n  throw new Error('TTS schema present but no provider populated');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reject empty placeholder provider objects in a config validator.","Smoke-test TTS after config edits."],"tags":["tts","config","provider","empty-schema"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}