HeyPuter/puter · critical · HttpError

unauthorized

unauthorized

Error message

Authentication required

What it means

Before converting, the driver reads Context.get('actor') — the request-scoped authenticated user from AsyncLocalStorage. If no actor is present (the request reached the driver without a valid user session), it throws 401 / unauthorized. This is the driver-level in-depth auth gate; the controller route is expected to enforce auth too, but the driver defends itself.

Source

Thrown at src/backend/drivers/ai-speech2speech/VoiceChangerDriver.ts:140

                400,
                `Speech-to-speech provider not found: ${args.provider}. Available: ${PROVIDERS.join(', ')}`,
                { legacyCode: 'bad_request' },
            );
        }

        if (args.test_mode) {
            return { url: SAMPLE_AUDIO_URL, content_type: 'audio/mpeg' };
        }

        if (!this.#apiKey) {
            throw new HttpError(500, 'ElevenLabs API key not configured', {
                legacyCode: 'internal_error',
            });
        }

        const actor = Context.get('actor');
        if (!actor)
            throw new HttpError(401, 'Authentication required', {
                legacyCode: 'unauthorized',
            });

        if (!args.audio) {
            throw new HttpError(400, '`audio` is required', {
                legacyCode: 'bad_request',
            });
        }

        const loaded = await loadFileInput(
            this.stores,
            this.services.fs,
            actor,
            args.audio,
            { maxBytes: MAX_AUDIO_FILE_SIZE },
        );

        const modelId = args.model_id || args.model || this.#defaultModelId;

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Ensure the call runs inside an authenticated HTTP request so the actor is set on the ALS Context.
  2. In tests use setupPuterTestEnv() and hit the real route so the actor is populated.
  3. Verify the controller route declares the auth gate in its RouteOptions.
Defensive patterns

Strategy: validation

Validate before calling

// client-side (puter.js)
if (!puter.auth.isSignedIn()) {
  await puter.auth.signIn();
}

Try / catch

try {
  await puter.ai.speech2speech(/* ... */);
} catch (e) {
  if (e?.code === 'unauthorized' || e?.status === 401) {
    await reAuthenticate();
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking the driver outside an authenticated request context: a background job, a unit test calling convert() directly, or a controller route that skipped the auth RouteOptions gate.

Common situations: Calling convert() in a Vitest unit test without booting the ALS Context; a route registered without auth middleware; an expired or missing session token reaching the driver.

Understand the failure class

Related errors


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