HeyPuter/puter · error · HttpError

unauthorized

unauthorized

Error message

Authentication required

What it means

ImageGenerationDriver.generate() reads Context.get('actor') at the top of the call; if no actor is present it throws HTTP 401. This means the request never passed through Puter's authentication middleware, so there is no authenticated user to bill, attribute, or permission against.

Source

Thrown at src/backend/drivers/ai-image/ImageGenerationDriver.ts:124

                    (model as { costs?: Record<string, number> }).costs ?? {},
                )) {
                    if (typeof raw !== 'number' || !Number.isFinite(raw))
                        continue;
                    out.push({
                        usageType: `${model.provider}:${model.id}:${costKey}`,
                        costValue: raw,
                        source: `driver:aiImage/${model.provider}`,
                    });
                }
            }
        }
        return out;
    }

    async generate(args: IGenerateParams): Promise<string> {
        const actor = Context.get('actor') as Actor | undefined;
        if (!actor)
            throw new HttpError(401, 'Authentication required', {
                legacyCode: 'unauthorized',
            });

        const puterOutputPath = args.puter_output_path;
        delete args.puter_output_path;

        // Validate the output path early — before spending credits.
        let resolvedOutputPath: string | undefined;
        if (puterOutputPath) {
            const username = actor.user?.username;
            const userId = actor.user?.id;
            if (!userId || !username) {
                throw new HttpError(
                    400,
                    'User ID required for puter_output_path',
                    { legacyCode: 'bad_request' },
                );
            }

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Ensure the route/driver endpoint declaring puter-image-generation carries the authentication gate (RouteOptions auth) so actor is populated.
  2. If invoking generate() programmatically, set Context actor first (or run inside an authenticated request).
  3. In tests, use setupPuterTestEnv() and authenticate a user before calling generate().

Example fix

// before — driver called with no auth context
await imageDriver.generate({ prompt: 'cat' });
// after — ensure auth sets the actor
// route-level: register the endpoint with the auth gate
extension.post('/drivers/call', { auth: true }, handler);
// or in tests:
const actor = await getTestUserActor();
await Context.run({ actor }, () => imageDriver.generate({ prompt: 'cat' }));
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the call runs inside an authenticated request.
const actor = Context.get('actor');
if (!actor) throw new Error('generate() must run with an authenticated actor');
await driver.generate(args);

Type guard

function hasActor(ctx) {
  const a = ctx.get('actor');
  return !!a && typeof a === 'object';
}

Prevention

When it happens

Trigger: Calling the image-generation driver from a context where auth was skipped — a misconfigured route/driver endpoint missing the auth gate, a background/internal invocation that forgot to set Context actor, or calling generate() directly in tests without a logged-in actor.

Common situations: New driver route registered without the auth RouteOptions gate; a test harness that calls the driver directly; an internal job that invokes the driver outside a request lifecycle.

Understand the failure class

Related errors


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