abpframework/abp · error · AbpValidationException

ModelState is not valid! See ValidationErrors for details.

Error message

ModelState is not valid! See ValidationErrors for details.

What it means

Thrown by ModelStateValidator.Validate after it collects all ASP.NET Core ModelStateDictionary errors into an AbpValidationResult. If any model-binding/validation errors exist, it raises AbpValidationException with this message and the collected errors as ValidationErrors. This is the ABP pipeline's central translation of ASP.NET Core model-state failures into ABP's exception/filter format.

Source

Thrown at framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ModelStateValidator.cs:19

using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Validation;

namespace Volo.Abp.AspNetCore.Mvc.Validation;

public class ModelStateValidator : IModelStateValidator, ITransientDependency
{
    public virtual void Validate(ModelStateDictionary modelState)
    {
        var validationResult = new AbpValidationResult();

        AddErrors(validationResult, modelState);

        if (validationResult.Errors.Any())
        {
            throw new AbpValidationException(
                "ModelState is not valid! See ValidationErrors for details.",
                validationResult.Errors
            );
        }
    }

    public virtual void AddErrors(IAbpValidationResult validationResult, ModelStateDictionary modelState)
    {
        if (modelState.IsValid)
        {
            return;
        }

        foreach (var state in modelState)
        {
            foreach (var error in state.Value.Errors)
            {
                validationResult.Errors.Add(new ValidationResult(error.ErrorMessage, new[] { state.Key }));

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. Inspect the ValidationErrors collection (or the ABP exception's data) to see exactly which fields failed and why.
  2. Fix the client request to satisfy the data-annotation / type constraints on the DTO.
  3. Add or correct [Required], [Range], [StringLength], etc. so the contract is explicit.
  4. If validation is unexpected, check that model binders and JSON serialization options match the DTO types.

Example fix

// before: POST { "age": null } to DTO with [Required] int Age -> ModelState invalid
// after: client sends { "age": 25 }
Defensive patterns

Strategy: validation

Validate before calling

// On the client, validate before posting; on the server, inspect ModelState:
if (!ModelState.IsValid)
{
    var errors = ModelState
        .Where(kv => kv.Value?.Errors.Count > 0)
        .Select(kv => $"{kv.Key}: {kv.Value.Errors[0].ErrorMessage}");
    // return 400 with the specific field errors
}

Type guard

null

Try / catch

try { modelStateValidator.Validate(ModelState); }
catch (AbpValidationException ex)
{ /* ex.ValidationErrors -> return 400 details to client */ }

Prevention

When it happens

Trigger: Calling ModelStateValidator.Validate(modelState) (or letting ABP's MVC validation filter call it) on a request whose ModelStateDictionary.IsValid is false - i.e. a field failed data-annotations, model binding, or [ApiController] automatic validation.

Common situations: Sending a DTO with a missing [Required] field, a wrong type (string where int expected), out-of-range values, or malformed JSON that fails model binding; enabling ABP's auto-validation on a controller that receives invalid input.

Related errors


AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13). Data as JSON: /api/errors/b960f5e3bc48f2f8. Report an issue: GitHub.