kgrzybek/modular-monolith-with-ddd · warning · InvalidCommandException
Command validation error
Error message
Command validation error
What it means
Thrown by the UserAccess module ValidationCommandHandlerDecorator. It wraps every UserAccess command handler, runs all FluentValidation validators for command T, and throws InvalidCommandException(errors) — whose message is the literal 'Command validation error' while the real detail lives in the Errors list. Distinguishes itself from Payments/Registrations by using a fixed summary message rather than forwarding validator messages as the exception message.
Source
Thrown at src/Modules/UserAccess/Infrastructure/Configuration/Processing/ValidationCommandHandlerDecorator.cs:32
public ValidationCommandHandlerDecorator(
IList<IValidator<T>> validators,
ICommandHandler<T> decorated)
{
this._validators = validators;
_decorated = decorated;
}
public async Task Handle(T command, CancellationToken cancellationToken)
{
var errors = _validators
.Select(v => v.Validate(command))
.SelectMany(result => result.Errors)
.Where(error => error != null)
.ToList();
if (errors.Any())
{
throw new InvalidCommandException(errors.Select(x => x.ErrorMessage).ToList());
}
await _decorated.Handle(command, cancellationToken);
}
}
}View on GitHub (pinned to 91c8ef24b4)
Solutions
- Inspect ex.Errors for the specific failing validators (the top-level message is generic).
- Correct the command values to satisfy each validator.
- Mirror validators on the client to fail fast.
- Update validator rules if a legitimate value is rejected.
Example fix
// before await _commandDispatcher.SendAsync(new ChangeUserPasswordCommand(login, "", "")); // after await _commandDispatcher.SendAsync(new ChangeUserPasswordCommand(login, "OldP@ss1!", "NewStrongP@ss1!"));
Defensive patterns
Strategy: validation
Validate before calling
var validator = new ChangeUserPasswordCommandValidator(); var result = await validator.ValidateAsync(cmd); if (!result.IsValid) return BadRequest(result.Errors.Select(e => e.ErrorMessage)); await _commandDispatcher.SendAsync(cmd);
Try / catch
try { await _commandDispatcher.SendAsync(cmd); }
catch (InvalidCommandException ex)
{ return BadRequest(new { errors = ex.Errors }); } // note: top-level message is generic; detail is in Errors Prevention
- Enforce password policy on the client before submit.
- Do not rely on the generic message; always surface ex.Errors.
- Keep validators in sync with UserAccess command DTOs.
When it happens
Trigger: Sending a UserAccess command (login, change password, add user, assign role) with properties failing a registered validator: empty login, password not meeting policy, missing role name, malformed email.
Common situations: Login with blank credentials; password change that violates policy; admin form missing role assignment; client skips client-side validation.
Related errors
- Command validation error
- {validator error messages}
- {validator error messages}
- {validator error messages}
- {validator error messages}
AI-assisted analysis of kgrzybek/modular-monolith-with-ddd@91c8ef24b4 (2026-08-13).
Data as JSON: /api/errors/647a69414dea57ba.
Report an issue: GitHub.