HeyPuter/puter · error · HttpError

unauthorized

unauthorized

Error message

Authentication required

What it means

TTSDriver.synthesize reads the authenticated actor from the request Context (ALS). If no actor is set — meaning the call did not pass an auth gate — it throws HTTP 401 (legacyCode unauthorized) before any provider routing. This guard ensures only authenticated sessions synthesize speech.

Source

Thrown at src/backend/drivers/ai-tts/TTSDriver.ts:156

                    if (Array.isArray(entries)) all.push(...entries);
                } catch {
                    // ignore — cost reporting is best-effort
                }
            }
        }
        return all;
    }

    /**
     * Synthesize speech from text, routed to the provider named by `provider`
     * (or the default when none is given).
     */
    async synthesize(
        args: ISynthesizeArgs,
    ): Promise<DriverStreamResult | { url: string; content_type: string }> {
        const actor = Context.get('actor');
        if (!actor)
            throw new HttpError(401, 'Authentication required', {
                legacyCode: 'unauthorized',
            });

        const providerName = this.#resolveProvider(args);
        const provider = this.#providers[providerName];
        if (!provider) {
            throw new HttpError(
                400,
                `TTS provider not configured: ${providerName}. Available: ${Object.keys(this.#providers).join(', ')}`,
                { legacyCode: 'bad_request' },
            );
        }

        return provider.synthesize(
            this.#providerArgs(providerName, args),
        ) as Promise<
            DriverStreamResult | { url: string; content_type: string }
        >;

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Ensure the caller is authenticated: pass a valid user/app token with the request.
  2. If invoking from backend code, populate Context with the actor (actor set in ALS) before calling synthesize.
  3. Confirm the route/driver path is behind the auth gate in its RouteOptions.
  4. Re-authenticate the user if the session expired.
Defensive patterns

Strategy: validation

Validate before calling

// Ensure an authenticated session exists before calling synthesize.
if (!puter.auth?.token && !sessionToken) {
  // redirect to sign-in / obtain a token
  return;
}
await driver.synthesize({ text: 'hi' });

Try / catch

try {
  await driver.synthesize({ text: 'hi' });
} catch (e) {
  if (e?.status === 401 || e?.fields?.legacyCode === 'unauthorized') {
    // re-authenticate the user, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking the puter-tts synthesize driver/route without a valid authenticated session, or calling TTSDriver.synthesize programmatically outside a request scope where Context.get('actor') was never populated.

Common situations: A route registered without the auth RouteOptions gate; a SDK call missing the auth token; server-internal code calling synthesize without establishing actor context; a token that expired mid-session.

Understand the failure class

Related errors


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