HeyPuter/puter · warning · HttpError

must_login_or_signup

must_login_or_signup

Error message

Temporary accounts are disabled

What it means

Thrown by POST /signup (HTTP 403, legacyCode 'must_login_or_signup') when the request is a temp signup (is_temp:true) AND the 'puter.signup.validate' extension set validateEvent.no_temp_user = true. It runs immediately after the abuse 'allow' gate, so it specifically signals that anonymous/temp accounts have been turned off by policy even though signups as a whole may be permitted. validateEvent.message overrides the default text if the extension supplied one.

Source

Thrown at src/backend/controllers/auth/AuthController.ts:909

        }
        if (!validateEvent.allow) {
            // Pass the trail id back to a blocked user as the Request Code (when
            // the harness stamped one), embedded in the message so the existing
            // signup-block UI surfaces it without a GUI change.
            const requestCode = validateEvent.trail_id;
            throw new HttpError(
                403,
                (validateEvent.message ?? 'Signup blocked') +
                    (requestCode ? ` Request Code: ${requestCode}` : ''),
                {
                    ...(validateEvent.code
                        ? { legacyCode: validateEvent.code as never }
                        : {}),
                },
            );
        }
        if (is_temp && validateEvent.no_temp_user) {
            throw new HttpError(
                403,
                validateEvent.message ?? 'Temporary accounts are disabled',
                {
                    legacyCode: 'must_login_or_signup',
                    ...(validateEvent.code
                        ? { legacyCode: validateEvent.code as never }
                        : {}),
                },
            );
        }
        const force_email_confirmation = Boolean(
            validateEvent.requires_email_confirmation,
        );
        const force_phone_verification =
            Boolean(validateEvent.requires_phone_verification) ||
            // Test/QA switch: force the SMS gate on every signup regardless of
            // reputation (see config.always_require_phone_verification).
            Boolean(this.config.always_require_phone_verification);

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Switch the client to a real signup (is_temp absent/false) with a username/email/password if anonymous access is no longer allowed.
  2. If you operate the server and temp users should be allowed, update the abuse-prevention extension so it does not set no_temp_user for this traffic.
  3. Catch this error specifically and redirect the user to the full signup or login flow rather than retrying the temp request.

Example fix

// before
await signup({ is_temp: true });

// after
try {
  await signup({ is_temp: true });
} catch (e) {
  if (e.statusCode === 403 && e.legacyCode === 'must_login_or_signup') {
    openSignupForm(); // real signup with email/password
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// no client pre-check exists; if your server exposes the policy, check it
if (policy disables temp users) { openRealSignupForm(); return; }

Try / catch

try {
  await signup({ is_temp: true });
} catch (e) {
  if (e.statusCode === 403 && e.legacyCode === 'must_login_or_signup') {
    openSignupForm(); // real signup
  } else throw e;
}

Prevention

When it happens

Trigger: POST /signup with is_temp:true on a deployment whose abuse-prevention extension disables temp users (no_temp_user=true). A real (non-temp) signup on the same deployment may still succeed.

Common situations: A deployment that requires real accounts and uses the validate hook to forbid temp users; an extension policy toggled on after launch, breaking clients that relied on temp-account creation; a client defaulting to is_temp:true for anonymous use.

Related errors


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