{"record":{"id":"eb284ab31a9fd49d","repo":"HeyPuter/puter","slug":"internal-error-eb284a","errorCode":"internal_error","errorMessage":"Speech-to-text provider not configured: ${providerName}","messagePattern":"Speech-to-text provider not configured: (.+?)","errorType":"http","errorClass":"HttpError","httpStatus":500,"severity":"error","filePath":"src/backend/drivers/ai-speech2txt/SpeechToTextDriver.ts","lineNumber":127,"sourceCode":"    async list(): Promise<string[]> {\n        return Object.keys(this.#providers);\n    }\n\n    async transcribe(args: ITranscribeArgs) {\n        return this.#provider(args).transcribe(this.#providerArgs(args));\n    }\n\n    async translate(args: ITranscribeArgs) {\n        return this.#provider(args).translate(this.#providerArgs(args));\n    }\n\n    // -- Provider routing --------------------------------------------\n\n    #provider(args: ITranscribeArgs): ISpeechToTextProvider {\n        const providerName = this.#resolveProvider(args);\n        const provider = this.#providers[providerName];\n        if (!provider) {\n            throw new HttpError(\n                500,\n                `Speech-to-text provider not configured: ${providerName}`,\n                { legacyCode: 'internal_error' },\n            );\n        }\n        return provider;\n    }\n\n    /**\n     * Decide which provider handles a call: an explicit `provider` wins, then\n     * the legacy driver alias the caller dispatched through, then the default.\n     */\n    #resolveProvider(args: { provider?: unknown }): string {\n        if (\n            args.provider !== undefined &&\n            args.provider !== null &&\n            args.provider !== ''\n        ) {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/ai-speech2txt/SpeechToTextDriver.ts#L109-L145","documentation":"The unified STT driver resolved a provider name (explicit, alias, or default) but no provider object was registered under that name in #providers. Providers register on boot regardless of credentials (so their model catalogues stay listable), so this only happens when the resolved name is not one of openai/xai at all — a server-side misconfiguration. Thrown as 500 / internal_error. Distinct from error 410: that fires when the name is unrecognized; this fires when a recognized name was never registered.","triggerScenarios":"A custom fork that added a provider alias in providerAliases.ts without a matching this.#providers[name] = new ... line in #registerProviders; a DEFAULT_SPEECH_TO_TEXT_PROVIDER set to an unregistered id.","commonSituations":"Fork that extended SPEECH_TO_TEXT_PROVIDERS but forgot the registration branch; a deployment where #registerProviders was overridden and dropped a provider.","solutions":["Ensure the resolved provider name has a matching registration line in SpeechToTextDriver.#registerProviders.","Call driver.list() to see which providers are actually configured.","Let the driver pick the default by not naming a provider."],"exampleFix":"// before: alias resolves 'whisper' -> 'openai' but openai was never registered\n// after — in #registerProviders\nthis.#providers['openai'] = new OpenAISpeechToTextProvider(deps, { apiKey });","handlingStrategy":"validation","validationCode":"const configured = await driver.list();\nif (!configured.includes(targetProvider)) {\n  throw new Error(`provider '${targetProvider}' not configured; available: ${configured.join(', ')}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await driver.transcribe(args);\n} catch (e) {\n  if (e?.legacyCode === 'internal_error' && /not configured/.test(e?.message ?? '')) {\n    // fall back to a provider returned by driver.list()\n  } else throw e;\n}","preventionTips":["Call driver.list() at app boot and cache the configured set.","Don't hardcode a provider name that may be disabled per-deployment.","Keep alias resolution and provider registration in sync when forking."],"tags":["config","provider-routing","speech2txt"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}