{"record":{"id":"93b5b26a6a293db6","repo":"gotify/server","slug":"failed-to-prepare-password-s","errorCode":null,"errorMessage":"failed to prepare password: %s","messagePattern":"failed to prepare password: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"api/user.go","lineNumber":197,"sourceCode":"//\t        $ref: \"#/definitions/Error\"\n//\t  401:\n//\t    description: Unauthorized\n//\t    schema:\n//\t        $ref: \"#/definitions/Error\"\n//\t  403:\n//\t    description: Forbidden\n//\t    schema:\n//\t        $ref: \"#/definitions/Error\"\nfunc (a *UserAPI) CreateUser(ctx *gin.Context) {\n\tuser := model.CreateUserExternal{}\n\tif err := ctx.Bind(&user); err == nil {\n\t\tif err := password.ValidateNewPassword(user.Pass); err != nil {\n\t\t\tctx.AbortWithError(http.StatusBadRequest, err)\n\t\t\treturn\n\t\t}\n\t\tpw, err := password.CreatePassword(user.Pass, a.PasswordStrength)\n\t\tif err != nil {\n\t\t\tctx.AbortWithError(http.StatusInternalServerError, fmt.Errorf(\"failed to prepare password: %s\", err))\n\t\t\treturn\n\t\t}\n\t\tinternal := &model.User{\n\t\t\tName:  user.Name,\n\t\t\tAdmin: user.Admin,\n\t\t\tPass:  pw,\n\t\t}\n\t\texistingUser, err := a.DB.GetUserByName(internal.Name)\n\t\tif success := successOrAbort(ctx, 500, err); !success {\n\t\t\treturn\n\t\t}\n\n\t\tvar requestedBy *model.User\n\t\tuid := auth.TryGetUserID(ctx)\n\t\tif uid != nil {\n\t\t\trequestedBy, err = a.DB.GetUserByID(*uid)\n\t\t\tif err != nil {\n\t\t\t\tctx.AbortWithError(http.StatusInternalServerError, fmt.Errorf(\"could not get user: %s\", err))","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/gotify/server/blob/14bfc256276775c425f988d621dccfe705de18ac/api/user.go#L179-L215","documentation":"In CreateUser, after validating the new password, the server hashes it with password.CreatePassword using the configured PasswordStrength. If hashing fails (e.g. invalid strength parameter or bcrypt/argon2 failure), the request is aborted with a 500 and \"failed to prepare password: <err>\". It indicates an internal password-hashing problem, not a bad password.","triggerScenarios":"POST to the user-creation endpoint with a password that passes ValidateNewPassword but fails password.CreatePassword — typically when a.PasswordStrength is misconfigured or out of the hashing library's accepted range.","commonSituations":"App.yaml/env sets an unsupported PasswordStrength value (e.g. cost outside bcrypt 4–31); embedding an alternative hasher that errors; resource exhaustion during key derivation.","solutions":["Fix the configured PasswordStrength (App settings) to a value the hashing library accepts.","Check the wrapped %s error for the concrete hashing failure and address it.","Verify the password passes ValidateNewPassword first; ensure the request sends a valid Pass field.","Upgrade/patch the password package if the hash function itself is failing."],"exampleFix":"// before (config)\nPASSWORD_STRENGTH=99\n// after\nPASSWORD_STRENGTH=11","handlingStrategy":"validation","validationCode":"if err := password.ValidateNewPassword(pass); err != nil {\n    return fmt.Errorf(\"invalid password: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if resp.StatusCode == http.StatusInternalServerError && strings.Contains(body, \"failed to prepare password\") {\n    // server-side hashing config issue; report to admin, don't retry\n}","preventionTips":["Keep PasswordStrength within the hasher's supported range.","Always validate passwords client- and server-side before hashing.","Validate hashing config at application startup."],"tags":["password","hashing","http-500"],"backgroundTag":"password-hash-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"}