fullstackhero/dotnet-starter-kit · error · CustomException

failed to change password

Error message

failed to change password

What it means

ChangePasswordAsync throws CustomException('failed to change password') when userManager.ChangePasswordAsync returns result.Succeeded == false. Typical Identity failures: wrong current password, new password below policy, or password reuse rules; the Identity error descriptions are attached to the exception.

Solutions

  1. Read the errors list on the exception — Identity reports the exact reason (e.g. 'PasswordTooShort', 'PasswordMismatch')
  2. Retry with the correct current password
  3. Pick a password meeting the configured Identity strength requirements
  4. Normalize/trim inputs client-side before submission

Example fix

// before
throw new Exception("change failed");
// after
var errors = result.Errors.Select(e => e.Description).ToList();
throw new CustomException("failed to change password", errors);
Defensive patterns

Strategy: try-catch

Validate before calling

if (newPassword != confirmNewPassword)
    return Results.BadRequest("Passwords do not match.");
if (newPassword is null || newPassword.Length < 8)
    return Results.BadRequest("Password must be at least 8 characters.");

Try / catch

try
{
    await passwordService.ChangePasswordAsync(currentPassword, newPassword, confirmNewPassword, userId, ct);
}
catch (CustomException ex)
{
    return Results.BadRequest(new { message = ex.Message, identityErrors = ex.Errors });
}

Prevention

When it happens

Trigger: Calling ChangePasswordAsync with an incorrect current password; newPassword violating strength/length/uniqueness policy; confirmNewPassword mismatching newPassword is caught earlier by validation, but Identity-side policy failures surface here.

Common situations: User typo in the current password; new password too weak per configured Identity options; account locked or password recently changed violating reuse policy; client sends untrimmed input with stray whitespace.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/254c42a1f04851ae. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Identity/Modules.Identity/Services/UserPasswordService.cs:98

        // Raise domain event for password reset
        var tenantId = multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id;
        user.RecordPasswordChanged(wasReset: true, tenantId);
        await db.SaveChangesAsync(cancellationToken);
    }

    public async Task ChangePasswordAsync(string password, string newPassword, string confirmNewPassword, string userId, CancellationToken cancellationToken = default)
    {
        var user = await userManager.FindByIdAsync(userId);

        _ = user ?? throw new NotFoundException("user not found");

        var result = await userManager.ChangePasswordAsync(user, password, newPassword);

        if (!result.Succeeded)
        {
            var errors = result.Errors.Select(e => e.Description).ToList();
            throw new CustomException("failed to change password", errors);
        }

        // Raise domain event for password change
        var tenantId = multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id;
        user.RecordPasswordChanged(wasReset: false, tenantId);
        await db.SaveChangesAsync(cancellationToken);

        // Update password expiry date
        await passwordExpiryService.UpdateLastPasswordChangeDateAsync(userId, cancellationToken);

        // Save to history
        await passwordHistoryService.SavePasswordHistoryAsync(userId, cancellationToken);
    }

    private void EnsureValidTenant()
    {
        if (string.IsNullOrWhiteSpace(multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id))
        {

View on GitHub (pinned to 3f2959e683)