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
- Switch the client to a real signup (is_temp absent/false) with a username/email/password if anonymous access is no longer allowed.
- 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.
- 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
- Don't default clients to is_temp:true if the deployment forbids temp users.
- Catch must_login_or_signup and redirect to a full signup or login.
- If temp users should be allowed, ensure the abuse extension doesn't set no_temp_user.
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.