{"record":{"id":"574e972ad3a694a6","repo":"gotify/server","slug":"password-must-not-be-empty","errorCode":null,"errorMessage":"password must not be empty","messagePattern":"password must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/password/password.go","lineNumber":11,"sourceCode":"package password\n\nimport (\n\t\"errors\"\n\n\t\"golang.org/x/crypto/bcrypt\"\n)\n\nfunc ValidateNewPassword(pw string) error {\n\tif pw == \"\" {\n\t\treturn errors.New(\"password must not be empty\")\n\t}\n\tif len([]byte(pw)) > 72 {\n\t\treturn bcrypt.ErrPasswordTooLong\n\t}\n\treturn nil\n}\n\n// CreatePassword returns a hashed version of the given password.\nfunc CreatePassword(pw string, strength int) ([]byte, error) {\n\thashedPassword, err := bcrypt.GenerateFromPassword([]byte(pw), strength)\n\treturn hashedPassword, err\n}\n\n// ComparePassword compares a hashed password with its possible plaintext equivalent.\nfunc ComparePassword(hashedPassword, password []byte) bool {\n\treturn bcrypt.CompareHashAndPassword(hashedPassword, password) == nil\n}\n","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/gotify/server/blob/14bfc256276775c425f988d621dccfe705de18ac/auth/password/password.go#L1-L29","documentation":"Validation error from password.ValidateNewPassword in auth/password/password.go: an empty password string was supplied where a new password is required. The function is called by CreateUser, ChangePassword, and the user-update handler before hashing, so user creation or password change is rejected with HTTP 400.","triggerScenarios":"POST /users (admin create user) or password-change endpoint with pass == \"\" or the pass field omitted; user-update (PUT) setting a password to an empty string instead of leaving it out.","commonSituations":"Client sends JSON without the pass field and the server treats empty string as 'set password'; forms with an optional password field submit empty values; API clients defaulting missing fields to empty strings in serialization.","solutions":["Omit the pass/pass field entirely when you don't want to change the password (empty string in update means 'no change' only if the handler checks; for create a real password is required)","Send a non-empty password when creating a user or changing a password","Also keep the password <= 72 bytes since the same validator enforces bcrypt's length limit"],"exampleFix":"// before\nawait api.updateUser(id, { name: 'bob', pass: '' });\n// after: only send pass when actually changing it\nconst payload = { name: 'bob' };\nif (newPassword) payload.pass = newPassword;\nawait api.updateUser(id, payload);","handlingStrategy":"validation","validationCode":"function validateNewPassword(pw) {\n  if (typeof pw !== 'string' || pw.length === 0) throw new Error('password must not be empty');\n  if (Buffer.byteLength(pw, 'utf8') > 72) throw new Error('password longer than 72 bytes');\n  return pw;\n}\nvalidateNewPassword(newPassword);","typeGuard":"function isValidPassword(pw) {\n  return typeof pw === 'string' && pw.length > 0 && Buffer.byteLength(pw, 'utf8') <= 72;\n}","tryCatchPattern":"try {\n  await api.createUser({ name, pass: pw });\n} catch (e) {\n  if (e.status === 400 && /password/.test(e.message)) {\n    throw new ValidationError('password rejected by server: ' + e.message);\n  }\n  throw e;\n}","preventionTips":["Validate password non-empty (and <=72 bytes) client-side before sending","When updating users, omit the pass field rather than sending an empty string","Enforce minimum-length rules in your UI to catch empties before submission","Remember the limit is bytes, not characters, for multibyte passwords"],"tags":["validation","password","http-400","user-management"],"backgroundTag":"password-validation-failed","analyzedSha":"14bfc256276775c425f988d621dccfe705de18ac","analyzedAt":"2026-09-05T12:52:36.781Z","contentChangedAt":"2026-09-05T12:52:36.781Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}