Mintplex-Labs/anything-llm · error

Username must start with a lowercase letter and only…

Error message

Username must start with a lowercase letter and only contain lowercase letters, numbers, underscores, hyphens, and periods

What it means

Thrown when the username passes both length checks but fails User.usernameRegex (/^[a-z][a-z0-9._@-]*$/): it must start with a lowercase letter and may then contain only lowercase letters, digits, periods, underscores, @ signs, and hyphens. It is a pre-database validator, so the write is rejected before Prisma runs. Uppercase letters, spaces, leading digits or hyphens, and non-ASCII characters are the usual offenders even though the message text omits @. Like the length check, User.update skips it when the username is unchanged.

Solutions

  1. Lowercase the username and strip spaces/invalid characters before submitting
  2. Reject leading digits, hyphens, and underscores client-side: the first character must be a lowercase letter
  3. Encode display names during LDAP/SSO sync (spaces to hyphens, drop uppercase) before calling create/update
  4. Validate locally against the exact pattern: /^[a-z][a-z0-9._@-]*$/ with 2-64 total characters

Example fix

// before
await User.create({ username: "John.Smith", password: hash });

// after
await User.create({ username: "john.smith", password: hash });
Defensive patterns

Strategy: validation

Validate before calling

const USERNAME_RE = /^[a-z][a-z0-9._@-]*$/;
function normalizeUsername(raw) {
  return String(raw ?? "").trim().toLowerCase();
}
const username = normalizeUsername(input.username);
if (!username || !USERNAME_RE.test(username) || username.length < 2) {
  return res.status(400).json({ error: "Invalid username format" });
}

Try / catch

try {
  await user.update(userId, { username });
} catch (e) {
  if (/Username must start with/i.test(e.message)) return res.status(400).json({ error: e.message });
  throw e;
}

Prevention

When it happens

Trigger: User.create with "John" or "John.Smith" (leading uppercase); "1user", "-john", or "_john" (first character is not a lowercase letter); "john smith" (embedded space); usernames with Unicode letters or pasted invisible whitespace.

Common situations: Signup or admin forms that do not lowercase or restrict the input; LDAP/SSO sync using display names like "Jane Doe"; migrating users from a system that allowed uppercase; copy-paste introducing trailing spaces or newlines.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/2a0b16473245f2c3. Report an issue: GitHub.

Appendix: source

Thrown at server/models/user.js:43

    "dailyMessageLimit",
    "bio",
  ],
  validations: {
    /**
     * Unix-style username regex:
     * - Must start with a lowercase letter
     * - Can contain lowercase letters, digits, underscores, hyphens, @ signs, and periods
     * - 2-64 characters long
     */
    username: (newValue = "") => {
      try {
        const username = String(newValue);
        if (username.length > 64)
          throw new Error("Username cannot be longer than 64 characters");
        if (username.length < 2)
          throw new Error("Username must be at least 2 characters");
        if (!User.usernameRegex.test(username))
          throw new Error(
            "Username must start with a lowercase letter and only contain lowercase letters, numbers, underscores, hyphens, and periods"
          );
        return username;
      } catch (e) {
        throw new Error(e.message);
      }
    },
    role: (role = "default") => {
      const VALID_ROLES = ["default", "admin", "manager"];
      if (!VALID_ROLES.includes(role)) {
        throw new Error(
          `Invalid role. Allowed roles are: ${VALID_ROLES.join(", ")}`
        );
      }
      return String(role);
    },
    dailyMessageLimit: (dailyMessageLimit = null) => {
      if (dailyMessageLimit === null) return null;

View on GitHub (pinned to 3aec848f28)