HeyPuter/puter · error · HttpError

temporary_account

temporary_account

Error message

Temporary account

What it means

Raised in `verifyIdentity` when the user has neither a password nor an email (a temp/anonymous account) and the route was NOT registered with `allowTempUsers: true`. Sensitive operations require a real account; temp accounts are only admitted where the route explicitly opts in (e.g. delete-own-user for temp accounts).

Source

Thrown at src/backend/core/http/middleware/userProtected.ts:207

    //     `revalidate_url` helper so the GUI can open the OIDC popup.
    //   - Otherwise accept a valid `puter_revalidation` cookie. Expiry,
    //     `purpose === 'revalidate'`, matching `user_uuid` all required.
    //   - Password account, neither credential → 403 `password_required`.
    const verifyIdentity: RequestHandler = async (
        req: Request,
        _res: Response,
        next: NextFunction,
    ) => {
        const user = req.userProtected?.user;
        if (!user)
            throw new HttpError(500, 'user-protected state missing', {
                legacyCode: 'internal_error',
            });

        const isTemp = user.password === null && user.email === null;
        if (isTemp) {
            if (allowTemp) return next();
            throw new HttpError(403, 'Temporary account', {
                legacyCode: 'temporary_account',
            });
        }

        const bodyPassword =
            typeof req.body?.password === 'string' ? req.body.password : null;
        if (bodyPassword) {
            if (user.password === null) {
                const fields = await buildRevalidateFields(
                    config,
                    oidcService,
                    user,
                );
                throw new HttpError(403, 'OIDC revalidation required', {
                    legacyCode: 'oidc_revalidation_required',
                    fields,
                });
            }

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Upgrade the temp account to a real one by setting an email and/or password.
  2. If temp users should pass this route, register it with `allowTempUsers: true`.
  3. Gate the UI so temp accounts cannot reach the sensitive flow.

Example fix

// before
const gate = createUserProtectedGate(deps);
// after
const gate = createUserProtectedGate(deps, { allowTempUsers: true });
Defensive patterns

Strategy: validation

Validate before calling

// Gate the UI on account type before reaching the sensitive flow:
const isTempAccount = (u) => u && u.password == null && u.email == null;
if (isTempAccount(user) && !routeAllowsTemp) { promptUpgradeAccount(); }

Type guard

const isTempAccount = (u) => !!(u && u.password == null && u.email == null);

Try / catch

try { await call(); }
catch (e) {
  if (e.code === 'temporary_account') { promptUpgradeAccount(); return; }
  throw e;
}

Prevention

When it happens

Trigger: A temp account (no password, no email) hits a userProtected route that did not set `allowTempUsers: true`.

Common situations: A guest/temp session used to attempt account operations; a route that should allow temp accounts but wasn't opted in.

Related errors


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