kgrzybek/modular-monolith-with-ddd · warning · InvalidCommandException
{validator error messages}
Error message
{validator error messages} What it means
Thrown by the Payments module ValidationCommandHandlerDecorator, which wraps every command handler. It runs all registered FluentValidation validators for the command T, collects every ValidationFailure.ErrorMessage, and if any exist throws InvalidCommandException(errors). The literal message '{validator error messages}' is a placeholder: the real messages come from the command's validators.
Source
Thrown at src/Modules/Payments/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 to see exactly which validators failed and which properties.
- Fix the offending command property to satisfy the validator (length, format, required-ness, allowed values).
- Run the same FluentValidation validators on the client/API layer before dispatching.
- Register/adjust validators if a legitimate value is being rejected.
Example fix
// before await _commandDispatcher.SendAsync(new ChangePriceListItemAttributesCommand(itemId, "", "", "", -1, "")); // after await _commandDispatcher.SendAsync(new ChangePriceListItemAttributesCommand(itemId, "PL", "MONTHLY", "PRO", 19.99m, "PLN"));
Defensive patterns
Strategy: validation
Validate before calling
var validator = new ChangePriceListItemAttributesCommandValidator(); 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 }); } Prevention
- Run the same FluentValidation validators client-side before dispatch.
- Read ex.Errors to find which property/validator failed.
- Keep command DTOs and validators in sync when adding fields.
When it happens
Trigger: Sending any Payments command whose properties fail a registered FluentValidation validator: null/empty required fields, strings exceeding length, invalid enum codes, negative money values, malformed Guids, etc.
Common situations: Client omits a required field; enum code not in the allowed catalog; money currency empty; integration test constructs a command by hand and skips required values.
Related errors
- {validator error messages}
- {validator error messages}
- {validator error messages}
- Command validation error
- Command validation error
AI-assisted analysis of kgrzybek/modular-monolith-with-ddd@91c8ef24b4 (2026-08-13).
Data as JSON: /api/errors/9a0722898d3688be.
Report an issue: GitHub.