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.
Solutions
- Ensure the route/driver endpoint declaring puter-image-generation carries the authentication gate (RouteOptions auth) so actor is populated.
- If invoking generate() programmatically, set Context actor first (or run inside an authenticated request).
- 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
- Register image-generation endpoints with the auth gate so actor is populated.
- Never call generate() outside an authenticated request lifecycle.
- In tests, authenticate a user (setupPuterTestEnv) before invoking the driver.
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12).
Data as JSON: /api/errors/4339762a09b37b1d.
Report an issue: GitHub.
Appendix: 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)