{"record":{"id":"c19d1cd3fa1bd803","repo":"danny-avila/LibreChat","slug":"no-stt-schema-is-set-did-you-configure-stt-in-the","errorCode":null,"errorMessage":"No STT schema is set. Did you configure STT in the custom config (librechat.yaml)?","messagePattern":"No STT schema is set\\. Did you configure STT in the custom config \\(librechat\\.yaml\\)\\?","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/server/services/Files/Audio/STTService.js","lineNumber":155,"sourceCode":"  }\n\n  /**\n   * Retrieves the configured STT provider and its schema.\n   * @param {ServerRequest} req - The request object.\n   * @returns {Promise<[string, Object, (string[]|undefined)]>} A promise that resolves to the provider name, its schema, and the section-level allowedAddresses exemption list.\n   * @throws {Error} If no STT schema is set, multiple providers are set, or no provider is set.\n   */\n  async getProviderSchema(req) {\n    const appConfig =\n      req.config ??\n      (await getAppConfig({\n        role: req?.user?.role,\n        userId: req?.user?.id,\n        tenantId: req?.user?.tenantId,\n      }));\n    const sttSchema = appConfig?.speech?.stt;\n    if (!sttSchema) {\n      throw new Error(\n        'No STT schema is set. Did you configure STT in the custom config (librechat.yaml)?',\n      );\n    }\n\n    const providers = Object.entries(sttSchema).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\n    const [provider, schema] = providers[0];\n    return [provider, schema, sttSchema.allowedAddresses];","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/server/services/Files/Audio/STTService.js#L137-L173","documentation":"STTService.getProviderSchema throws when appConfig.speech.stt is falsy. The whole STT subsystem reads its wiring from the `speech.stt` block resolved via getAppConfig (typically librechat.yaml, filtered by role/userId/tenantId). An absent or empty block means no provider can be selected, so the request is rejected before any strategy lookup.","triggerScenarios":"Any STT request (POST /api/speech/stt) when librechat.yaml has no `speech.stt` section, or when role/tenant-scoped config resolution returns an object whose `speech.stt` is undefined/null.","commonSituations":"STT enabled in the client UI but never configured server-side; librechat.yaml not mounted into the container; config file path misconfigured; tenant-scoped override returns an empty speech block; upgrade that renamed the config key.","solutions":["Add a `speech.stt` block with exactly one populated provider (e.g. openai or azureOpenAI) to librechat.yaml.","Confirm librechat.yaml is mounted and parsed — check startup logs for the config load line.","Restart the API server so getAppConfig picks up the change."],"exampleFix":"# before\nspeech: {}\n\n# after (librechat.yaml)\nspeech:\n  stt:\n    openai:\n      apiKey: '${STT_API_KEY}'\n      model: 'whisper-1'","handlingStrategy":"validation","validationCode":"const appConfig = await getAppConfig({ role, userId, tenantId });\nconst stt = appConfig?.speech?.stt;\nif (!stt) {\n  return res.status(503).json({ error: 'STT is not configured on this server.' });\n}","typeGuard":"/** @param {unknown} c */\nfunction hasSttSchema(c) {\n  return !!c && typeof c === 'object' && 'speech' in c\n    && !!c.speech && typeof c.speech === 'object'\n    && 'stt' in c.speech && !!c.speech.stt\n    && typeof c.speech.stt === 'object';\n}","tryCatchPattern":null,"preventionTips":["Treat the speech.stt block as required infrastructure for STT routes; gate the route on its presence.","Mount librechat.yaml via a volume/configmap and log the config load at startup.","Run a config smoke test in CI that asserts the expected speech block exists."],"tags":["stt","config","librechat-yaml","schema"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}