DynamicWhere.ex
DynamicWhere.exv2.1.0·docs

Error Codes Reference

Every validation failure in DynamicWhere.ex throws a LogicException (which inherits from Exception). The Message property carries one of the 22 stable error strings listed below, so you can pattern‑match them in middleware and surface meaningful problems to API callers.

How errors are raised

Validation runs eagerly — before any expression tree is built or any SQL is emitted. If your Filter, Segment, Summary, ConditionGroup, GroupBy, or PageBy shape is invalid, the corresponding extension method throws synchronously (even on the async overloads, the throw happens before the first await). The thrown type is always LogicException and the message is always one of the rows in the table below.

Surfacing errors in an API
Wrap the call in a try / catch (LogicException ex) and map it to a 400 Bad Request with the message as the validation reason. Other exception types should bubble up as 500s.
app.MapPost("/customers/search", async (Filter filter, AppDbContext db) =>
{
    try
    {
        var result = await db.Customers.ToListAsync(filter);
        return Results.Ok(result);
    }
    catch (LogicException ex)
    {
        // ex.Message is one of the stable error codes below
        return Results.BadRequest(new { error = ex.Message });
    }
});

All 22 error codes

Codes wrapped in (parens) are parameterized — the bracketed token in the message is replaced at runtime with the offending operator, alias, aggregator, type, or field name.

Error CodeMessageTriggered When
SetsUniqueSortListOfConditionsSetsMustHasUniqueSortValueDuplicate Sort in ConditionSets
ConditionsUniqueSortAnyListOfConditionsMustHasUniqueSortValueDuplicate Sort in Conditions
SubConditionsGroupsUniqueSortAnyListOfSubConditionsGroupsMustHasUniqueSortValueDuplicate Sort in SubConditionGroups
RequiredIntersectionConditionsSetOfIndex[1-N]MustHasIntersectionMissing Intersection on set index 1+
InvalidFieldConditionMustHasValidFieldNameEmpty or invalid field name
InvalidValueConditionValuesAreNullOrWhiteSpaceNull / whitespace value
RequiredValuesConditionWithOperator[In-IIn-NotIn-INotIn]MustHasOneOrMoreValuesIn / NotIn with 0 values
NotRequiredValuesConditionWithOperator[IsNull-IsNotNull]MustHasNoValuesIsNull / IsNotNull with values
RequiredTwoValueConditionWithOperator[Between-NotBetween]MustHasOnlyTwoValuesBetween without exactly 2 values
RequiredOneValue(op)ConditionWithOperator[{op}]MustHasOnlyOneValueSingle‑value operator with wrong count
InvalidPageNumberPageNumberMustBeGreaterThanZeroPageNumber ≤ 0
InvalidPageSizePageSizeMustBeGreaterThanZeroPageSize ≤ 0
MustHaveFieldsMustHasFieldsEmpty fields list in Select
InvalidFormatInvalidFormatValue doesn't parse for declared DataType
InvalidAliasAggregationMustHasValidAliasEmpty or dotted alias
GroupByMustHaveFieldsGroupByMustHasAtLeastOneFieldGroupBy with no fields
GroupByFieldsMustBeUniqueGroupByFieldsMustBeUniqueDuplicate GroupBy fields
GroupByFieldCannotBeComplexTypeGroupByFieldCannotBeComplexTypeNon‑simple GroupBy field
GroupByFieldCannotBeCollectionGroupByFieldCannotBeCollectionTypeCollection GroupBy field
AggregationFieldMustBeSimpleTypeAggregationFieldMustBeSimpleTypeComplex aggregation field
AggregationFieldCannotBeCollectionAggregationFieldCannotBeCollectionTypeCollection aggregation field
AggregationAliasesMustBeUniqueAggregationAliasesMustBeUniqueDuplicate aliases
AggregationAliasCannotBeGroupByField(alias)AggregationAlias[{alias}]CannotBeUsedInGroupByFieldsAlias clashes with a GroupBy field
UnsupportedAggregatorForType(agg, type)Aggregator[{agg}]IsNotSupportedForFieldType[{type}]Invalid aggregator for the field's type
SummaryOrderFieldMustExistInGroupByOrAggregate(f)SummaryOrderField[{f}]MustExistInGroupByFieldsOrAggregateByAliasesOrder on a non‑grouped, non‑aggregated field
HavingFieldMustExistInAggregateByAlias(f)HavingField[{f}]MustExistInAggregateByAliasesHaving references an unknown alias
Why messages and not numeric codes?
The messages are stable across versions and self‑documenting, which keeps client error handling readable. If you need numeric codes for i18n, map them in your API layer using the Error Code column as the key — the Error Code names are also stable.

Each error is raised by a specific validation entry point. Follow the link for the full validation rules and the exact shape that triggers each code:

  • Condition validation → InvalidField, InvalidValue, RequiredValues, NotRequiredValues, RequiredTwoValue, RequiredOneValue(op), InvalidFormat.
  • ConditionGroup validation → SetsUniqueSort, ConditionsUniqueSort, SubConditionsGroupsUniqueSort, RequiredIntersection.
  • Page validation → InvalidPageNumber, InvalidPageSize.
  • GroupBy validation → MustHaveFields, GroupByMustHaveFields, GroupByFieldsMustBeUnique, GroupByFieldCannotBeComplexType, GroupByFieldCannotBeCollection.
  • Summary validation → InvalidAlias, AggregationFieldMustBeSimpleType, AggregationFieldCannotBeCollection, AggregationAliasesMustBeUnique, AggregationAliasCannotBeGroupByField(alias), UnsupportedAggregatorForType(agg, type), SummaryOrderFieldMustExistInGroupByOrAggregate(f), HavingFieldMustExistInAggregateByAlias(f).
  • Segment validation → inherits all ConditionGroup + Page errors and additionally enforces RequiredIntersection for sets at index 1 and above.

See also