{"record":{"id":"fbc664bcc6bf0d5e","repo":"fullstackhero/dotnet-starter-kit","slug":"userid-must-be-provided","errorCode":null,"errorMessage":"UserId must be provided.","messagePattern":"UserId must be provided\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":400,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Features/v1/Users/ToggleUserStatus/ToggleUserStatusCommandHandler.cs","lineNumber":22,"sourceCode":"\nnamespace FSH.Modules.Identity.Features.v1.Users.ToggleUserStatus;\n\npublic sealed class ToggleUserStatusCommandHandler : ICommandHandler<ToggleUserStatusCommand, Unit>\n{\n    private readonly IUserService _userService;\n\n    public ToggleUserStatusCommandHandler(IUserService userService)\n    {\n        _userService = userService;\n    }\n\n    public async ValueTask<Unit> Handle(ToggleUserStatusCommand command, CancellationToken cancellationToken)\n    {\n        ArgumentNullException.ThrowIfNull(command);\n\n        if (string.IsNullOrWhiteSpace(command.UserId))\n        {\n            throw new ArgumentException(\"UserId must be provided.\", nameof(command.UserId));\n        }\n\n        await _userService.ToggleStatusAsync(command.ActivateUser, command.UserId, cancellationToken).ConfigureAwait(false);\n\n        return Unit.Value;\n    }\n}","sourceCodeStart":4,"sourceCodeEnd":29,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Features/v1/Users/ToggleUserStatus/ToggleUserStatusCommandHandler.cs#L4-L29","documentation":"ToggleUserStatusCommandHandler validates that command.UserId is a non-empty string before delegating to the user service; a null/whitespace id raises ArgumentException naming the UserId property. It's a guard against activating/deactivating an unspecified user.","triggerScenarios":"POST/PUT toggle-user-status with a body where userId is null, empty string, or whitespace — e.g. a form submitted before a user was selected, or JSON property-name mismatch so the field never binds.","commonSituations":"Frontend list row without a selected id; client serializing camelCase while model binding expects a different casing; calling the handler directly in tests with a default command; migration code constructing the command without UserId.","solutions":["Always supply a valid, non-empty user id in the request body / command.","Check JSON casing and property names so UserId actually binds (userId vs UserId).","Add or rely on the ToggleUserStatusCommandValidator to reject empty ids earlier with a friendly message."],"exampleFix":"// before\nawait mediator.Send(new ToggleUserStatusCommand { ActivateUser = true, UserId = \"\" });\n// after\nif (string.IsNullOrWhiteSpace(userId)) throw new ValidationException(\"UserId is required\");\nawait mediator.Send(new ToggleUserStatusCommand { ActivateUser = true, UserId = userId });","handlingStrategy":"validation","validationCode":"const errors = {};\nif (!userId || !userId.trim()) errors.userId = 'User id is required';\nif (Object.keys(errors).length) throw new ValidationError(errors);","typeGuard":"function hasUserId(cmd) {\n  return typeof cmd?.userId === 'string' && cmd.userId.trim().length > 0;\n}","tryCatchPattern":"try { await mediator.Send(new ToggleUserStatusCommand(activate, userId)); }\ncatch (ArgumentException ex) when (ex.ParamName == \"UserId\") {\n    return Results.BadRequest(new { error = \"UserId is required\" });\n}","preventionTips":["Validate ids in the command validator so users get 400 not 500-style failures.","Bind JSON with matching casing (userId) and add FluentValidation rules.","Disable the UI toggle until a user row is selected.","Log the raw payload when binding produces an empty id to spot contract mismatches."],"tags":["validation","identity","arguments"],"backgroundTag":"missing-required-argument","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"}