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

  1. Inspect ValidationException.Errors to see which properties failed and why, then fix the request payload.
  2. Validate input client-side (e.g. zod + react-hook-form) mirroring server rules.
  3. Register a behavior/middleware that maps ValidationException to a 400 ProblemDetails response.
  4. 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

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


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)