Aggregation engine filters silently discard unrecognized enum values
Problem
Five aggregation engine filters resolve their formatter: lambda via filter_map or values_at(...).compact, which silently discards any value it cannot recognize: pipelines.source, deployments.status, merge_requests.state_id, duo_workflows.status, ai_usage_events.event.
The GraphQL adapter only rejects blank argument values, before the formatter runs (lib/gitlab/database/aggregation/graphql/adapter.rb:22). The formatter itself runs later, in lib/gitlab/database/aggregation/query_plan/filter.rb:17. A list containing only unrecognized values passes the blank check, then becomes an empty list after formatting.
Arel renders an empty IN as 1=0 and an empty NOT IN as 1=1 (activerecord-7.2.3.1/lib/arel/visitors/to_sql.rb:600 and :617). So status: ["typo"] returns no rows, and statusNot: ["typo"] returns every row. Neither raises an error.
This asymmetry became public API surface when https://gitlab.com/gitlab-org/gitlab/-/issues/629296 added the 27 *Not arguments, but the value-discarding behavior predates it and already affects the 27 positive-filter arguments. It is pinned deliberately in existing specs, e.g. ee/spec/models/analytics/aggregation_engines/merge_requests_spec.rb, in examples named 'returns no results when all state names are unrecognized' and 'silently drops unrecognized state names mixed with valid ones'.
A validation mechanism for this already exists but isn't wired to filters: Gitlab::Database::Aggregation::ParameterizedDefinition supports an in: option that validates allowed values and adds a request error (lib/gitlab/database/aggregation/parameterized_definition.rb:66-80). This is why totalCount(source: 'nonexistent') returns an "Invalid value(s) for parameter" error today, while a filter given the same unrecognized value does not.
Proposal
Extend the in: validation path to FilterDefinition so an unrecognized filter value produces a request error instead of being silently dropped, for both positive and *Not arguments.
This changes existing behavior for the 27 current positive-filter arguments: today's silent empty result becomes an error. That needs a deprecation/communication decision, not a silent behavior change — coordinate before shipping.
Out of scope
- Changing how NULL values interact with exclusion filters (tracked separately).
- The
exact_match_pairrollout itself, done in https://gitlab.com/gitlab-org/gitlab/-/issues/629296.