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

  1. Pick a different, non-reserved username.
  2. If this is a test fixture, change the fixture username to something outside the reserved list (e.g. 'tester_a').
  3. 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

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


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