HeyPuter/puter · error · HttpError
username_already_in_use
username_already_in_use
Error message
This username is not available.
What it means
Thrown by POST /signup when body.username (case-insensitively) is in the RESERVED_USERNAMES set: admin, administrator, root, system, puter, www, api, support, help, info, contact, mail, email, null, undefined, test, guest, anonymous, user, users. Despite the misleading legacyCode 'username_already_in_use', this is a reservation guard, not a duplicate-DB check (that is a separate, later error). HTTP 400.
Source
Thrown at src/backend/controllers/auth/AuthController.ts:733
throw new HttpError(400, 'username must be a string.', {
legacyCode: 'bad_request',
});
if (!USERNAME_REGEX.test(body.username)) {
throw new HttpError(
400,
'Username can only contain letters, numbers and underscore (_).',
{ legacyCode: 'bad_request' },
);
}
if (body.username.length > USERNAME_MAX_LENGTH) {
throw new HttpError(
400,
`Username cannot be longer than ${USERNAME_MAX_LENGTH} characters.`,
{ legacyCode: 'bad_request' },
);
}
if (RESERVED_USERNAMES.has(body.username.toLowerCase())) {
throw new HttpError(400, 'This username is not available.', {
legacyCode: 'username_already_in_use',
});
}
if (!is_temp) {
if (!body.email)
throw new HttpError(400, 'Email is required', {
legacyCode: 'bad_request',
});
if (typeof body.email !== 'string')
throw new HttpError(400, 'email must be a string.', {
legacyCode: 'bad_request',
});
if (!validator.isEmail(body.email))
throw new HttpError(
400,
'Please enter a valid email address.',
{ legacyCode: 'bad_request' },
);View on GitHub (pinned to 908ec23eda)
Solutions
- Pick a different, non-reserved username.
- If this is a test fixture, change the fixture username to something outside the reserved list (e.g. 'tester_a').
- Surface the reserved list to the client so the UI can pre-validate availability.
Example fix
// before
await signup({ username: 'admin', email, password }); // -> 400 username_already_in_use
// after
const RESERVED = ['admin','administrator','root','system','puter','www','api','support','help','info','contact','mail','email','null','undefined','test','guest','anonymous','user','users'];
if (RESERVED.includes(username.toLowerCase())) {
return showFieldError('username', 'That username is reserved');
}
await signup({ username, email, password }); Defensive patterns
Strategy: validation
Validate before calling
const RESERVED = new Set(['admin','administrator','root','system','puter','www','api','support','help','info','contact','mail','email','null','undefined','test','guest','anonymous','user','users']);
if (RESERVED.has(String(username).toLowerCase())) {
return showFieldError('username', 'That username is reserved');
} Type guard
const isReservedUsername = (v) => typeof v === 'string' && RESERVED.has(v.toLowerCase());
Prevention
- Keep the client-side reserved list in sync with the server's RESERVED_USERNAMES set.
- Compare case-insensitively (.toLowerCase()) just like the server does.
- Use non-reserved names in test fixtures (avoid 'admin', 'test', 'guest').
When it happens
Trigger: POST /signup where body.username.toLowerCase() is one of the reserved entries — including case variants ('Admin', 'ROOT', 'Guest'), since the check lowercases the submitted value before lookup.
Common situations: A user picking 'admin' or 'support'; an integration test that always signs up a user named 'test' or 'guest'; a seeding/import script that maps imported roles ('root','user') directly to usernames.
Related errors
- bad_request
- password_required
- signup_disabled
- Signup blocked Request Code: ${requestCode}
- must_login_or_signup
AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12).
Data as JSON: /api/errors/3e0ff7a5c2b21f79.
Report an issue: GitHub.