{"record":{"id":"082725d15fb153c6","repo":"fullstackhero/dotnet-starter-kit","slug":"an-error-occurred-while-confirming-0","errorCode":null,"errorMessage":"An error occurred while confirming {0}","messagePattern":"An error occurred while confirming (.+?)","errorType":"exception","errorClass":"CustomException","httpStatus":400,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Services/UserRegistrationService.cs","lineNumber":89,"sourceCode":"        return user.Id;\n    }\n\n    public async Task<string> ConfirmEmailAsync(string userId, string code, string tenant, CancellationToken cancellationToken)\n    {\n        EnsureValidTenant();\n\n        var user = await userManager.Users\n            .Where(u => u.Id == userId && !u.EmailConfirmed)\n            .FirstOrDefaultAsync(cancellationToken);\n\n        _ = user ?? throw new CustomException(\"An error occurred while confirming E-Mail.\");\n\n        code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code));\n        var result = await userManager.ConfirmEmailAsync(user, code);\n\n        return result.Succeeded\n            ? string.Format(CultureInfo.InvariantCulture, \"Account Confirmed for E-Mail {0}. You can now use the /api/tokens endpoint to generate JWT.\", user.Email)\n            : throw new CustomException(string.Format(CultureInfo.InvariantCulture, \"An error occurred while confirming {0}\", user.Email));\n    }\n\n    public async Task AdminConfirmEmailAsync(string userId, CancellationToken cancellationToken = default)\n    {\n        EnsureValidTenant();\n\n        var user = await userManager.Users\n            .Where(u => u.Id == userId)\n            .FirstOrDefaultAsync(cancellationToken)\n            ?? throw new NotFoundException($\"User {userId} was not found.\");\n\n        // Idempotent: a second confirm is a no-op rather than an error.\n        if (user.EmailConfirmed)\n        {\n            return;\n        }\n\n        user.EmailConfirmed = true;","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Services/UserRegistrationService.cs#L71-L107","documentation":"ConfirmEmailAsync throws CustomException('An error occurred while confirming {0}') when UserManager.ConfirmEmailAsync returns a failed IdentityResult — the user was found and unconfirmed, but the provided code did not validate (wrong, expired, or corrupted token). The message includes the email to help the user retry.","triggerScenarios":"The confirmation code was Base64Url-decoded but rejected: token generated for a different purpose/user, invalidated by a security stamp change (password reset, profile update that rotates the stamp), tampering, or truncation of the code from the email client.","commonSituations":"Email clients wrapping/breaking the long code in the URL; user requested a password reset after the email was generated (stamp changed, old token invalid); link copy-paste losing characters; data-protection keys changed between environments invalidating old tokens.","solutions":["Request a new confirmation email and use the freshest link/code.","Ensure the full code is copied — check the email client didn't wrap or truncate the URL token.","Avoid changing the password or security stamp between requesting and confirming; re-request if you did.","Verify data-protection key persistence across instances/restarts so issued tokens remain valid."],"exampleFix":"// caller: send the pristine code from the email link unchanged\n// service: log identity errors for diagnosis\nif (!result.Succeeded)\n{\n    var errors = string.Join(\"; \", result.Errors.Select(e => e.Description));\n    logger.LogWarning(\"Email confirmation failed for {Email}: {Errors}\", user.Email, errors);\n    throw new CustomException(string.Format(CultureInfo.InvariantCulture, \"An error occurred while confirming {0}\", user.Email));\n}","handlingStrategy":"retry","validationCode":"// ensure the full code arrived intact\nconst code = new URLSearchParams(location.search).get('code');\nif (!code || code.length < 20 || /[\\s]/.test(code)) showError('Confirmation link appears incomplete — request a new email.');","typeGuard":null,"tryCatchPattern":"try { await confirmEmail(userId, code); }\ncatch (e) { if (isBadRequest(e)) { await resendConfirmation(email); show('We sent a fresh confirmation link.'); } else { throw e; } }","preventionTips":["Request a new confirmation email if password or profile changed since the link was issued (security stamp invalidates tokens).","Use HTML email templates that prevent URL line-wrapping/truncation.","Persist data-protection keys across instances so tokens stay valid.","Never hand-edit or trim the code parameter from links."],"tags":["identity","email-confirmation","token-validation"],"backgroundTag":"invalid-token","analyzedSha":"3f2959e683e9f83f13e55e1678c9119f63c7e8e5","analyzedAt":"2026-09-15T22:20:53.684Z","contentChangedAt":"2026-09-15T22:20:53.684Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}