HeyPuter/puter · error · HttpError

unauthorized

unauthorized

Error message

Authentication required

What it means

Raised at the top of the AI chat `complete()` driver when `Context.get('actor')` is null — there is no authenticated actor in the request-scoped AsyncLocalStorage. The AI endpoint requires authentication; anonymous completion is not permitted.

Source

Thrown at src/backend/drivers/ai-chat/ChatCompletionDriver.ts:307

                    if (typeof raw !== 'number' || !Number.isFinite(raw))
                        continue;
                    out.push({
                        usageType: `${model.provider}:${model.id}:${costKey}`,
                        ucentsPerUnit: raw,
                        unit: 'token',
                        source: `driver:aiChat/${model.provider}`,
                        costs_currency: model.costs_currency,
                    });
                }
            }
        }
        return out;
    }

    async complete(args: ICompleteArguments): Promise<IChatCompleteResult> {
        const actor = Context.get('actor');
        if (!actor)
            throw new HttpError(401, 'Authentication required', {
                legacyCode: 'unauthorized',
            });

        let intendedProvider = args.provider || '';
        if (!args.model && !intendedProvider) {
            intendedProvider = 'azure-openai'; // default provider
        }
        if (
            !args.model &&
            intendedProvider &&
            this.#providers[intendedProvider]
        ) {
            args.model = this.#providers[intendedProvider].getDefaultModel();
        }

        let model = this.#resolveModel(args.model, intendedProvider);
        if (!model) {
            throw new HttpError(400, `Model not found: ${args.model}`, {

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Authenticate before calling the AI endpoint (send the app/API/session token).
  2. Ensure the route runs the auth gate that sets the actor in Context.
  3. If calling the driver from non-request code, wrap the call in a Context.run(...) that sets actor.
  4. Verify ALS propagation across awaited boundaries.

Example fix

// before
puter.ai.chat('hi'); // no auth
// after — ensure a token is set first
puter.setAuthToken(apiToken);
puter.ai.chat('hi');
Defensive patterns

Strategy: validation

Validate before calling

// Ensure an auth token is present before calling AI:
if (!hasAuthToken()) { throw new Error('Authentication required for AI calls'); }

Try / catch

try { await aiChat(); }
catch (e) {
  if (e.code === 'unauthorized') { routeToLogin(); return; }
  throw e;
}

Prevention

When it happens

Trigger: Calling the AI chat complete driver/endpoint without auth, or with auth middleware that didn't populate the actor; or a code path that lost the Context (ALS) across an async boundary so `Context.get('actor')` returns undefined.

Common situations: Missing auth header/token; the route isn't behind the auth gate; a custom integration calling the driver directly outside a request context; ALS context dropped by an unawaited/incorrectly-bound callback.

Understand the failure class

Related errors


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