HeyPuter/puter · error · HttpError

internal_error

internal_error

Error message

Speech-to-text provider not configured: ${providerName}

What it means

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.

Source

Thrown at src/backend/drivers/ai-speech2txt/SpeechToTextDriver.ts:127

    async list(): Promise<string[]> {
        return Object.keys(this.#providers);
    }

    async transcribe(args: ITranscribeArgs) {
        return this.#provider(args).transcribe(this.#providerArgs(args));
    }

    async translate(args: ITranscribeArgs) {
        return this.#provider(args).translate(this.#providerArgs(args));
    }

    // -- Provider routing --------------------------------------------

    #provider(args: ITranscribeArgs): ISpeechToTextProvider {
        const providerName = this.#resolveProvider(args);
        const provider = this.#providers[providerName];
        if (!provider) {
            throw new HttpError(
                500,
                `Speech-to-text provider not configured: ${providerName}`,
                { legacyCode: 'internal_error' },
            );
        }
        return provider;
    }

    /**
     * Decide which provider handles a call: an explicit `provider` wins, then
     * the legacy driver alias the caller dispatched through, then the default.
     */
    #resolveProvider(args: { provider?: unknown }): string {
        if (
            args.provider !== undefined &&
            args.provider !== null &&
            args.provider !== ''
        ) {

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Ensure the resolved provider name has a matching registration line in SpeechToTextDriver.#registerProviders.
  2. Call driver.list() to see which providers are actually configured.
  3. Let the driver pick the default by not naming a provider.

Example fix

// before: alias resolves 'whisper' -> 'openai' but openai was never registered
// after — in #registerProviders
this.#providers['openai'] = new OpenAISpeechToTextProvider(deps, { apiKey });
Defensive patterns

Strategy: validation

Validate before calling

const configured = await driver.list();
if (!configured.includes(targetProvider)) {
  throw new Error(`provider '${targetProvider}' not configured; available: ${configured.join(', ')}`);
}

Try / catch

try {
  await driver.transcribe(args);
} catch (e) {
  if (e?.legacyCode === 'internal_error' && /not configured/.test(e?.message ?? '')) {
    // fall back to a provider returned by driver.list()
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Fork that extended SPEECH_TO_TEXT_PROVIDERS but forgot the registration branch; a deployment where #registerProviders was overridden and dropped a provider.

Related errors


AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12). Data as JSON: /api/errors/eb284ab31a9fd49d. Report an issue: GitHub.