{"record":{"id":"2a0b16473245f2c3","repo":"Mintplex-Labs/anything-llm","slug":"username-must-start-with-a-lowercase-letter-and-on","errorCode":null,"errorMessage":"Username must start with a lowercase letter and only contain lowercase letters, numbers, underscores, hyphens, and periods","messagePattern":"Username must start with a lowercase letter and only contain lowercase letters, numbers, underscores, hyphens, and periods","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"server/models/user.js","lineNumber":43,"sourceCode":"    \"dailyMessageLimit\",\n    \"bio\",\n  ],\n  validations: {\n    /**\n     * Unix-style username regex:\n     * - Must start with a lowercase letter\n     * - Can contain lowercase letters, digits, underscores, hyphens, @ signs, and periods\n     * - 2-64 characters long\n     */\n    username: (newValue = \"\") => {\n      try {\n        const username = String(newValue);\n        if (username.length > 64)\n          throw new Error(\"Username cannot be longer than 64 characters\");\n        if (username.length < 2)\n          throw new Error(\"Username must be at least 2 characters\");\n        if (!User.usernameRegex.test(username))\n          throw new Error(\n            \"Username must start with a lowercase letter and only contain lowercase letters, numbers, underscores, hyphens, and periods\"\n          );\n        return username;\n      } catch (e) {\n        throw new Error(e.message);\n      }\n    },\n    role: (role = \"default\") => {\n      const VALID_ROLES = [\"default\", \"admin\", \"manager\"];\n      if (!VALID_ROLES.includes(role)) {\n        throw new Error(\n          `Invalid role. Allowed roles are: ${VALID_ROLES.join(\", \")}`\n        );\n      }\n      return String(role);\n    },\n    dailyMessageLimit: (dailyMessageLimit = null) => {\n      if (dailyMessageLimit === null) return null;","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/models/user.js#L25-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Lowercase the username and strip spaces/invalid characters before submitting","Reject leading digits, hyphens, and underscores client-side: the first character must be a lowercase letter","Encode display names during LDAP/SSO sync (spaces to hyphens, drop uppercase) before calling create/update","Validate locally against the exact pattern: /^[a-z][a-z0-9._@-]*$/ with 2-64 total characters"],"exampleFix":"// before\nawait User.create({ username: \"John.Smith\", password: hash });\n\n// after\nawait User.create({ username: \"john.smith\", password: hash });","handlingStrategy":"validation","validationCode":"const USERNAME_RE = /^[a-z][a-z0-9._@-]*$/;\nfunction normalizeUsername(raw) {\n  return String(raw ?? \"\").trim().toLowerCase();\n}\nconst username = normalizeUsername(input.username);\nif (!username || !USERNAME_RE.test(username) || username.length < 2) {\n  return res.status(400).json({ error: \"Invalid username format\" });\n}","typeGuard":null,"tryCatchPattern":"try {\n  await user.update(userId, { username });\n} catch (e) {\n  if (/Username must start with/i.test(e.message)) return res.status(400).json({ error: e.message });\n  throw e;\n}","preventionTips":["Autolowercase and trim username input in the UI before submit","Mirror the server pattern with the input's pattern attribute","Map display names to slug-style usernames during provisioning"],"tags":["validation","regex","username","user-management"],"backgroundTag":"username-validation-failed","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}