HeyPuter/puter · error · HttpError

bad_request

bad_request

Error message

User ID required for puter_output_path

What it means

When a caller passes puter_output_path (write the result into the user's filesystem), generate() needs actor.user.id and actor.user.username to resolve and write the path. If either is missing it throws HTTP 400 before doing any work. The check exists so credits aren't spent on a generation whose output can't be stored.

Source

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

    }

    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' },
                );
            }
            resolvedOutputPath = this.#resolveOutputPath(
                puterOutputPath,
                username,
            );
            await this.#assertWriteAccess(actor, resolvedOutputPath);
        }

        let modelId =
            typeof args.model === 'string'
                ? args.model.trim().toLowerCase()
                : undefined;
        let intendedProvider =
            args.provider ?? (Context.get('driverName') as string | undefined);

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Do not send puter_output_path for actors without a full user (id + username).
  2. Fix the upstream auth so actor.user.id and actor.user.username are always populated for real users.
  3. Omit puter_output_path and handle the returned URL/data-URI yourself if the actor is partial.

Example fix

// before
await driver.generate({ prompt, puter_output_path: '/x.png' }); // actor.user incomplete
// after — only set output path for fully identified users
const out = actor?.user?.id && actor?.user?.username
  ? { puter_output_path: '/x.png' }
  : {};
await driver.generate({ prompt, ...out });
Defensive patterns

Strategy: validation

Validate before calling

const u = actor?.user;
const out = (u?.id && u?.username) ? { puter_output_path } : {};
await driver.generate({ prompt, ...out });

Type guard

function hasFullUser(actor) {
  return !!(actor?.user?.id && actor?.user?.username);
}

Prevention

When it happens

Trigger: An authenticated actor whose user object lacks id or username (partial/anonymous actor, misbuilt auth) supplies puter_output_path; the driver refuses to proceed.

Common situations: An auth flow that populates actor but not actor.user; a service account / app user without a username; testing with a stub actor missing user fields.

Related errors


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