{"record":{"id":"f2eed19b2563f320","repo":"fullstackhero/dotnet-starter-kit","slug":"update-profile-failed","errorCode":null,"errorMessage":"Update profile failed","messagePattern":"Update profile failed","errorType":"exception","errorClass":"CustomException","httpStatus":400,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Services/UserProfileService.cs","lineNumber":115,"sourceCode":"        {\n            await storageService.RemoveAsync(imageUri.ToString(), cancellationToken);\n            user.ImageUrl = null;\n        }\n\n        user.FirstName = firstName;\n        user.LastName = lastName;\n        string? currentPhoneNumber = await userManager.GetPhoneNumberAsync(user);\n        if (phoneNumber != currentPhoneNumber)\n        {\n            await userManager.SetPhoneNumberAsync(user, phoneNumber);\n        }\n\n        var result = await userManager.UpdateAsync(user);\n        await signInManager.RefreshSignInAsync(user);\n\n        if (!result.Succeeded)\n        {\n            throw new CustomException(\"Update profile failed\");\n        }\n    }\n\n    public async Task SetImageUrlAsync(string userId, string? imageUrl, CancellationToken cancellationToken)\n    {\n        EnsureValidTenant();\n        var user = await userManager.FindByIdAsync(userId)\n            ?? throw new NotFoundException(\"user not found\");\n\n        user.ImageUrl = string.IsNullOrWhiteSpace(imageUrl)\n            ? null\n            : new Uri(imageUrl, UriKind.RelativeOrAbsolute);\n\n        var result = await userManager.UpdateAsync(user);\n        if (!result.Succeeded)\n        {\n            throw new CustomException(\"Update profile image failed\");\n        }","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Services/UserProfileService.cs#L97-L133","documentation":"UpdateAsync throws CustomException('Update profile failed') when UserManager.UpdateAsync returns a non-succeeded IdentityResult after the profile fields were applied. The identity store rejected the change (e.g. validation or concurrency failure) even though the user was found and the code path reached the save.","triggerScenarios":"IdentityResult errors such as ConcurrencyFailure (security stamp/row mismatch), invalid PhoneNumber format, duplicate UserName/Email updates, or store-level constraint violations during profile update.","commonSituations":"Two tabs/devices saving the profile concurrently (stamp conflict); phone number values failing identity's phone validation; DB constraint issues; custom UserManager validators rejecting the change.","solutions":["Inspect result.Errors (log or surface them) to see the concrete IdentityError descriptions.","Retry the update if it was a concurrency (ConcurrencyFailure) conflict, re-reading the user first.","Fix the offending field value (e.g. valid phone number, unique email).","Check UserManager validator options and any DB unique constraints conflicting with the new values."],"exampleFix":"// before\nvar result = await userManager.UpdateAsync(user);\nif (!result.Succeeded) throw new CustomException(\"Update profile failed\");\n// after (caller side: surface identity errors)\nif (!result.Succeeded)\n{\n    var desc = string.Join(\"; \", result.Errors.Select(e => e.Description));\n    logger.LogWarning(\"Profile update failed: {Errors}\", desc);\n    throw new CustomException($\"Update profile failed: {desc}\");\n}","handlingStrategy":"try-catch","validationCode":"if (phoneNumber && !/^\\+?[0-9\\s().-]{7,20}$/.test(phoneNumber)) throw new Error('Invalid phone number format');","typeGuard":null,"tryCatchPattern":"try { await updateProfile(payload); }\ncatch (e) { if (e.status === 409 || e.status === 400) { await retryWithFreshFetch(); } else { throw e; } }","preventionTips":["Avoid concurrent profile edits from multiple tabs; reload before editing.","Validate phone/email fields client-side against identity's rules.","Log result.Errors server-side to diagnose identity rejections.","Keep EF concurrency token handling consistent (migrations up to date)."],"tags":["identity","update","validation"],"backgroundTag":"database-write-failed","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"}