Skip to content

fix(filter): report an unknown property in arithmetic as unknown - #151

Merged
pdevito3 merged 1 commit into
mainfrom
fm/qk-breaking-arithmetic-unknown
Oct 9, 2026
Merged

pdevito3 merged 1 commit into
mainfrom
fm/qk-breaking-arithmetic-unknown

Conversation

@pdevito3

@pdevito3 pdevito3 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

For later consideration in a major version. Do not merge now. #134 restored the v1.14.2 behavior to keep v1.x compatible (restore commit a3a4d54). This PR re-applies the behavior of af5c3f7 (#113). The captain decides on this PR separately.

Summary

An unknown property in an arithmetic clause gets the same result as an unknown property in any other filter clause:

  • If AllowUnknownProperties is false (the default), QueryKit throws UnknownFilterPropertyException.
  • If AllowUnknownProperties is true, QueryKit ignores the clause. IgnoredClauseBehavior controls the result, like for other ignored clauses.

The changes:

  • QueryKit/FilterParser.cs: a new FindUnknownArithmeticSegment walks both sides of the arithmetic comparison before the parser builds the expression.
  • QueryKit/PropertyResolver.cs: Resolve now calls a new ResolveWithoutDepthCheck, so arithmetic can resolve a property without MaxPropertyDepth. The result of Resolve does not change.

v1.14.2 behavior (and main)

An unknown property in arithmetic throws ArgumentException ("Property 'Nope' not found on type 'TestingPerson'"). This also occurs when AllowUnknownProperties is true. A query name, a derived property, or a custom operation name in arithmetic also throws ArgumentException.

New behavior

Arithmetic supports only entity members. A name that is not a member is unknown:

  • Without AllowUnknownProperties, the parser throws UnknownFilterPropertyException ("The filter property 'Nope' was not recognized.").
  • With AllowUnknownProperties, the parser ignores the clause.

The check uses the same member lookup as other clauses. It does not apply MaxPropertyDepth (item P, #138) or PreventFilter (item I, #136).

Example

var config = new QueryKitConfiguration(config =>
{
    config.IgnoredClauseBehavior = IgnoredClauseBehavior.Remove;
    config.AllowUnknownProperties = true;
});
FilterParser.ParseFilter<TestingPerson>("""(Nope + 1) > 3 || Age > 100""", config);
  • v1.14.2 and main: ArgumentException: Property 'Nope' not found on type 'TestingPerson'.
  • This PR: x => (x.Age > 100).

Without the configuration, (Nope + 1) > 3 throws UnknownFilterPropertyException on this PR.

Justification

AllowUnknownProperties is documented as "unknown properties will be ignored". On v1.14.2, arithmetic ignores this setting. The README also says that an unknown filter property throws UnknownFilterPropertyException. On v1.14.2, arithmetic throws ArgumentException, so an API that maps QueryKitException to a 400 returns a 500 for this input.

Migration

  • If your code catches ArgumentException for an unknown property in arithmetic, catch UnknownFilterPropertyException (or QueryKitException) instead.
  • If you set AllowUnknownProperties, an arithmetic clause on an unknown property no longer throws. QueryKit ignores the clause.

README

The "Supported Features" list under "Arithmetic Expressions" gets one new item, "Unknown Properties". It states the exception, the AllowUnknownProperties result, and that arithmetic supports only entity members. The sections "Allow Unknown Properties" and "Error Handling" already describe the new behavior and do not change.

Interaction with other PRs

Tests

Unit (QueryKit.UnitTests/PropertyResolverTests.cs), from main before #134:

  • unknown_property_in_arithmetic_throws_when_unknown_properties_are_allowed becomes unknown_property_in_arithmetic_removes_the_clause_when_unknown_properties_are_allowed.
  • unknown_property_on_the_right_side_of_arithmetic_throws_when_unknown_properties_are_allowed becomes unknown_property_on_the_right_side_of_arithmetic_removes_the_clause_when_unknown_properties_are_allowed.
  • unknown_property_in_arithmetic_throws_an_argument_exception becomes unknown_property_in_arithmetic_is_not_recognized.

Unit, changed for this PR alone:

Integration (QueryKit.IntegrationTests/Tests/PropertyResolverTests.cs): unknown_property_in_arithmetic_removes_the_clause_when_unknown_properties_are_allowed comes back.

dotnet test: 470 unit tests and 298 Postgres integration tests (Testcontainers) pass, 0 failures.

Rebase on main

This branch is rebased on current main. The only conflict was in the integration tests, where main added tests at the same place.

An unknown property in arithmetic threw ArgumentException, also when AllowUnknownProperties was true. An API that maps QueryKitException to 400 returned 500. An unknown property in arithmetic now gets the same result as in any other clause: UnknownFilterPropertyException by default, and an ignored clause with AllowUnknownProperties. IgnoredClauseBehavior controls the ignored clause.

Behavior change: catch UnknownFilterPropertyException or QueryKitException instead of ArgumentException. With AllowUnknownProperties, the clause no longer throws.

Examples:
  (Nope + 1) > 3
    before: ArgumentException: Property 'Nope' not found on type 'TestingPerson'
    after:  UnknownFilterPropertyException: The filter property 'Nope' was not recognized.
  (Nope + 1) > 3 || Age > 100 (AllowUnknownProperties, IgnoredClauseBehavior.Remove)
    before: ArgumentException
    after:  x => (x.Age > 100)
@pdevito3
pdevito3 force-pushed the fm/qk-breaking-arithmetic-unknown branch from b875aaf to e2cbe3a Compare October 9, 2026 20:46
@pdevito3 pdevito3 changed the title fix(filter)!: report an unknown property in arithmetic as unknown fix(filter): report an unknown property in arithmetic as unknown Oct 9, 2026
@pdevito3
pdevito3 merged commit d125876 into main Oct 9, 2026
2 checks passed
@pdevito3
pdevito3 deleted the fm/qk-breaking-arithmetic-unknown branch October 9, 2026 20:48
pdevito3 added a commit that referenced this pull request Oct 9, 2026
An unknown property in arithmetic threw ArgumentException, also when AllowUnknownProperties was true. An API that maps QueryKitException to 400 returned 500. An unknown property in arithmetic now gets the same result as in any other clause: UnknownFilterPropertyException by default, and an ignored clause with AllowUnknownProperties. IgnoredClauseBehavior controls the ignored clause.

Behavior change: catch UnknownFilterPropertyException or QueryKitException instead of ArgumentException. With AllowUnknownProperties, the clause no longer throws.

Examples:
  (Nope + 1) > 3
    before: ArgumentException: Property 'Nope' not found on type 'TestingPerson'
    after:  UnknownFilterPropertyException: The filter property 'Nope' was not recognized.
  (Nope + 1) > 3 || Age > 100 (AllowUnknownProperties, IgnoredClauseBehavior.Remove)
    before: ArgumentException
    after:  x => (x.Age > 100)
pdevito3 added a commit that referenced this pull request Oct 9, 2026
Brings the fixes that landed on main (#175 to #198, #142, #118, #151, #165, #127) into v2. The v2 code already has each of these fixes, so each conflict keeps the v2 side.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant