HeyPuter/puter · error · HttpError

forbidden

forbidden

Error message

Account suspended

What it means

Raised by `assertNotSuspended` when the user row's `suspended` flag is truthy. Suspended accounts are blocked from all gated access and surface under the generic `forbidden` legacy code.

Source

Thrown at src/backend/core/http/middleware/gates.ts:396

            403,
            'Please verify your phone number to continue',
            {
                legacyCode: 'phone_verification_required' as never,
            },
        );
    }
    if (user?.requires_card_verification) {
        throw new HttpError(403, 'Please verify your card to continue', {
            legacyCode: 'card_verification_required' as never,
        });
    }
};

export const assertNotSuspended = (
    user: { suspended?: unknown } | undefined,
): void => {
    if (user?.suspended) {
        throw new HttpError(403, 'Account suspended', {
            legacyCode: 'forbidden',
        });
    }
};

/**
 * Reject unless the actor is acting through one of the named apps.
 * App-under-user actors are permitted iff `actor.app.uid` is in the allowList;
 * non-app actors are rejected.
 *
 * Implies `requireAuth`. Doesn't pair sensibly with `requireUserActor` (a
 * user-only actor has no app), but if both are set we reject loudly here.
 */
export const allowedAppIdsGate = (
    allowedAppUids: readonly string[],
): RequestHandler => {
    const allowList = new Set(allowedAppUids);
    return (req, _res, next) => {

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Contact support to resolve the suspension.
  2. As admin, clear the `suspended` flag on the user row once resolved.
  3. Verify the suspension was intended and not a stale flag.
Defensive patterns

Strategy: try-catch

Type guard

const isSuspended = (u) => !!(u && u.suspended);

Try / catch

try { await call(); }
catch (e) {
  if (e.code === 'forbidden' && /suspended/i.test(e.message)) { showAccountSuspended(); return; }
  throw e;
}

Prevention

When it happens

Trigger: Any request from an account whose `suspended` flag is set hits a route guarded by `assertNotSuspended` (or the userProtected chain's suspension check).

Common situations: Account suspended by an admin or automated moderation for a ToS/abuse violation; a test account left suspended; flag set erroneously.

Related errors


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