Skip to content

Backend: PropertyValueException when saving PasswordHistory during password reset #286

@africanitem

Description

@africanitem

Backend Issue: PropertyValueException when saving PasswordHistory

Labels: bug, backend, high-priority, authentication

Summary

When resetting a user's password via the /public/resetPassword endpoint, the backend throws a PropertyValueException when attempting to save password history. The password is successfully updated, but password history is not saved.

Error Details

org.hibernate.PropertyValueException: not-null property references a null or transient value: com.simpleaccounts.entity.User.userEmail

Location: apps/backend/src/main/java/com/simpleaccounts/rest/usercontroller/UserRestHelper.java
Method: savePasswordHistory(Integer userId, String password, Integer createdBy, Integer lastUpdatedBy, Boolean isActive)

Impact

  • User Impact: Password reset appears to fail even though password is updated
  • Data Integrity: Password history is not being saved
  • System Reliability: Inconsistent behavior in password reset flow

Steps to Reproduce

  1. Register a new user or use an existing user
  2. Request a password reset via /public/forgotPassword endpoint
  3. Use the reset token to call /public/resetPassword endpoint with a new password
  4. Observe the backend logs for PropertyValueException
  5. Verify that password was updated but password history was not saved

Expected Behavior

  1. Password reset should complete successfully
  2. Password should be updated in USER_CREDENTIAL table ✅ (works)
  3. Password history should be saved in PASSWORD_HISTORY table ❌ (fails)
  4. API should return HTTP 200 with success message ❌ (returns 500)

Actual Behavior

  1. Password is updated in USER_CREDENTIAL table ✅
  2. Password history is NOT saved in PASSWORD_HISTORY table ❌
  3. API returns HTTP 500 with error message "Unable To Set Password." ❌
  4. Exception is logged: PropertyValueException: not-null property references a null or transient value: com.simpleaccounts.entity.User.userEmail

Root Cause

The PasswordHistory entity has a @ManyToOne(fetch = FetchType.EAGER) relationship with User. When saving PasswordHistory, Hibernate attempts to validate the User entity, which appears to be detached or not fully loaded, causing it to treat it as a new entity and attempt to persist it. During this process, it validates that userEmail is not null, which fails.

Attempted Fixes

The following approaches were tried but did not resolve the issue:

  1. Changed persist to update for User entity
  2. Reloaded user from database before updating
  3. Added validation to ensure userEmail is not null
  4. Used EntityManager.getReference() to get a managed proxy reference
  5. Used EntityManager.merge() to ensure entity is managed
  6. Used EntityManager.find() directly to get managed entity
  7. Created custom query findPasswordHistoriesByUserId to query by userId
  8. Created native SQL insert insertPasswordHistory to insert without loading User entity

Proposed Solutions

See .issue-backend-password-history.md for detailed proposed solutions.

Related Files

  • apps/backend/src/main/java/com/simpleaccounts/rest/usercontroller/UserRestHelper.java
  • apps/backend/src/main/java/com/simpleaccounts/rest/Logincontroller/LoginRestController.java
  • apps/backend/src/main/java/com/simpleaccounts/entity/PasswordHistory.java
  • apps/backend/src/main/java/com/simpleaccounts/entity/User.java
  • apps/backend/src/main/java/com/simpleaccounts/repository/PasswordHistoryRepository.java

Test Coverage

  • ✅ Playwright E2E test exists: apps/frontend/e2e/reset-password-complete.spec.ts
  • ✅ Test correctly identifies the failure
  • ⚠️ Test currently expects failure (should be updated once issue is fixed)

Priority

High - This affects a critical user flow (password reset) and causes inconsistent behavior.

Additional Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions