fullstackhero/dotnet-starter-kit · warning · FluentValidation.ValidationException
ValidationException(failures)
Error message
ValidationException(failures)
What it means
ValidationBehavior is a Mediator pipeline behavior that runs all registered FluentValidation validators for an incoming command/query. If any validation errors are collected, it throws ValidationException(failures) and the handler never executes. The exception carries the full list of property-level failures.
Solutions
- Inspect ValidationException.Errors to see which properties failed and why, then fix the request payload.
- Validate input client-side (e.g. zod + react-hook-form) mirroring server rules.
- Register a behavior/middleware that maps ValidationException to a 400 ProblemDetails response.
- Update the corresponding {Name}Validator if a rule is wrong or newly added and breaks legit callers.
Example fix
// before: dispatching unvalidated input
await mediator.Send(new CreateProductCommand(""));
// after: check validation result shape
try {
await mediator.Send(new CreateProductCommand(dto.Name));
} catch (ValidationException vex) {
var problems = vex.Errors.GroupBy(e => e.PropertyName)
.ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray());
return Results.ValidationProblem(problems);
} Defensive patterns
Strategy: try-catch
Validate before calling
// client-side mirror of the server validator (zod example)
const schema = z.object({ name: z.string().min(1, 'Name is required') });
schema.parse(command); // throws before the request is sent Type guard
bool IsValid<T>(T message, IEnumerable<IValidator<T>> validators) =>
validators.All(v => v.Validate(new ValidationContext<T>(message)).IsValid); Try / catch
try {
await mediator.Send(command);
} catch (ValidationException vex) {
var errors = vex.Errors.GroupBy(e => e.PropertyName)
.ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray());
return Results.ValidationProblem(errors); // 400
} Prevention
- Validate forms in the UI (react-hook-form + zod) matching server rules.
- Always register a {Name}Validator for new commands/queries — the architecture tests enforce it.
- When a validator changes, search for all callers and update payloads.
When it happens
Trigger: Dispatching any command/query whose input violates an {Name}Validator rule (empty required strings, out-of-range numbers, invalid format), causing failures.Count > 0 in ValidationBehavior.Handle.
Common situations: Frontend sending empty payloads; missing required fields when calling API endpoints directly (Postman/OpenAPI); new validator rules added that break existing callers; null DTO fields from deserialization.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- File exceeds max size of
- File exceeds max size of
- A category cannot be its own parent.
- Product not found.
- Image not found on product .
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/47347fcd379f0057.
Report an issue: GitHub.
Appendix: source
Thrown at src/BuildingBlocks/Web/Mediator/Behaviors/ValidationBehavior.cs:42
if (_validators.Length > 0)
{
var context = new ValidationContext<TMessage>(message);
List<ValidationFailure> failures;
if (_validators.Length == 1)
{
var result = await _validators[0].ValidateAsync(context, cancellationToken).ConfigureAwait(false);
failures = result.Errors;
}
else
{
var results = await Task.WhenAll(_validators.Select(v => v.ValidateAsync(context, cancellationToken))).ConfigureAwait(false);
failures = results.SelectMany(r => r.Errors).ToList();
}
if (failures.Count > 0)
throw new ValidationException(failures);
}
return await next(message, cancellationToken).ConfigureAwait(false);
}
}View on GitHub (pinned to 3f2959e683)