fullstackhero/dotnet-starter-kit · error · CustomException

Passwords do not match.

Error message

Passwords do not match.

What it means

Thrown as a CustomException (400) by the static ValidatePasswordMatch helper, called from RegisterAsync, when the password and confirmPassword fields differ. A pure pre-persistence check so Identity never sees mismatched passwords; the fix is always on the caller's side. Note the comparison is ordinal/exact — whitespace and case matter.

Solutions

  1. Compare the two values client-side before submitting and show a field-level error
  2. Ensure the request serializer maps confirmPassword explicitly (no missing/renamed property)
  3. Trim client inputs consistently if your policy allows, or enforce no-whitespace passwords
  4. Use a show-password toggle so users can verify the typed password

Example fix

// before
if (password !== confirmPasswordField.value.trim()) return; // silent skip
// after
if (password !== confirmPassword) {
  setError('confirmPassword', { message: 'Passwords do not match.' });
  return;
}
await register({ password, confirmPassword });
Defensive patterns

Strategy: validation

Validate before calling

function validate(password: string, confirmPassword: string): string | null { return password === confirmPassword ? null : 'Passwords do not match.'; }

Type guard

bool PasswordsMatch(RegisterRequest r) => r is not null && !string.IsNullOrEmpty(r.Password) && r.Password == r.ConfirmPassword;

Try / catch

catch (CustomException ex) when (ex.Message == "Passwords do not match.") { return Results.BadRequest(new { field = "confirmPassword", message = ex.Message }); }

Prevention

When it happens

Trigger: Registration request whose password and confirmPassword JSON properties differ; frontend forgot to bind the confirm field; client sending only one of the two fields (confirm defaults to null/empty).

Common situations: User typos in the confirm box or has Caps Lock on; autocomplete fills only the first field; API consumers (Postman/scripts) omit confirmPassword; leading/trailing spaces from copy-paste.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Modules/Identity/Modules.Identity/Services/UserRegistrationService.cs:233

            ?? email.Split('@')[0];

        return (firstName, lastName, userName);
    }

    private async Task<string> EnsureUniqueUserNameAsync(string userName)
    {
        if (await userManager.FindByNameAsync(userName) is not null)
        {
            return $"{userName}_{Guid.NewGuid():N}"[..20];
        }
        return userName;
    }

    private static void ValidatePasswordMatch(string password, string confirmPassword)
    {
        if (password != confirmPassword)
        {
            throw new CustomException(
                "Passwords do not match.",
                errors: null,
                HttpStatusCode.BadRequest);
        }
    }

    private async Task<FshUser> CreateUserWithPasswordAsync(
        string firstName,
        string lastName,
        string email,
        string userName,
        string password,
        string phoneNumber)
    {
        var user = new FshUser
        {
            Email = email,
            FirstName = firstName,

View on GitHub (pinned to 3f2959e683)