{"record":{"id":"13168828d9a8cbf8","repo":"immich-app/immich","slug":"wrong-password","errorCode":null,"errorMessage":"Wrong password","messagePattern":"Wrong password","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/auth.service.ts","lineNumber":133,"sourceCode":"      throw new BadRequestException('Invalid logout token: it must contain either a sub or a sid claim');\n    }\n\n    const deletedSessionIds = await this.sessionRepository.invalidateOAuth({\n      oauthSid: claims.sid,\n      oauthId: claims.sub,\n    });\n\n    for (const sessionId of deletedSessionIds) {\n      await this.eventRepository.emit('SessionDelete', { sessionId });\n    }\n  }\n\n  async changePassword(auth: AuthDto, dto: ChangePasswordDto): Promise<UserAdminResponseDto> {\n    const { password, newPassword } = dto;\n    const user = await this.userRepository.getForChangePassword(auth.user.id);\n    const isValid = this.validateSecret(password, user.password);\n    if (!isValid) {\n      throw new BadRequestException('Wrong password');\n    }\n\n    const hashedPassword = await this.cryptoRepository.hashBcrypt(newPassword, SALT_ROUNDS);\n\n    const updatedUser = await this.userRepository.update(user.id, {\n      password: hashedPassword,\n      shouldChangePassword: false,\n    });\n\n    await this.eventRepository.emit('AuthChangePassword', {\n      userId: user.id,\n      currentSessionId: auth.session?.id,\n      invalidateSessions: dto.invalidateSessions,\n    });\n\n    return mapUserAdmin(updatedUser);\n  }\n","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/immich-app/immich/blob/f48d4b332127ad365ba256108799ca8f571d2dd5/server/src/services/auth.service.ts#L115-L151","documentation":"changePassword first verifies the user's current password by comparing it against the stored bcrypt hash via validateSecret. If the supplied current password does not match, the update is aborted with a 400 'Wrong password' so an attacker with an open session cannot silently take over the account credentials.","triggerScenarios":"Calling PUT /api/auth/password (changePassword) with a `password` field that does not match the user's currently stored password, even if `newPassword` is valid.","commonSituations":"User typo or caps-lock when re-entering the current password; password was changed on another device/session; client caching a stale password after a password reset; password managed by an external auth provider (OAuth/LDAP) so no local password matches.","solutions":["Re-enter the correct current password and retry the change-password request.","If the password is forgotten, use the password reset flow or have an admin reset it, then change it.","Check that the user account actually authenticates locally (not solely via OAuth/LDAP) before attempting password change."],"exampleFix":"// before\nawait api.authenticationApi.changePassword({ password: oldGuess, newPassword });\n// after\nconst ok = await verifyCurrentPassword(oldGuess); // prompt again if false\nif (ok) await api.authenticationApi.changePassword({ password: oldGuess, newPassword });","handlingStrategy":"try-catch","validationCode":"if (!currentPassword || currentPassword.length === 0) {\n  throw new Error('Current password is required to change password');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.authenticationApi.changePassword({ password, newPassword });\n} catch (e) {\n  if (e.status === 400 && e.message === 'Wrong password') {\n    // re-prompt user for current password\n  }\n  throw e;\n}","preventionTips":["Always verify the current password with the user before submitting.","Handle 'Wrong password' by re-prompting rather than retrying blindly (avoid lockouts).","Sync password state across devices after a change."],"tags":["authentication","password","credentials"],"backgroundTag":"authentication-required","analyzedSha":"f48d4b332127ad365ba256108799ca8f571d2dd5","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}