Skip to content

fix(shared): multi-select "contains any" filter matcher should use OR semantics - #23010

Merged
etiennejouan merged 2 commits into
twentyhq:mainfrom
winklemad:fix-multiselect-contains-any-matcher
Jul 21, 2026
Merged

etiennejouan merged 2 commits into
twentyhq:mainfrom
winklemad:fix-multiselect-contains-any-matcher

Conversation

@winklemad

@winklemad winklemad commented Jul 18, 2026 •

Copy link
Copy Markdown
Contributor

The in-memory isMatchingMultiSelectFilter evaluated the containsAny operand with Array.every, which requires a record to hold all selected options. But containsAny means "any overlap": the server evaluates it as a Postgres array-overlap (field::text[] && ARRAY[...]), and the "Contains" UI operand for a MULTI_SELECT field builds exactly this operand — both match on at least one shared option.

So the matcher disagreed with the server. In a "Tags contains any of [A, B]" view, an optimistic create/update of a record whose tags are just [A] was treated as not matching, so it failed to appear (or was wrongly dropped) until a refetch; DOES_NOT_CONTAIN (built as not { containsAny }) inverted the same way. The same helper backs the row-level-permission predicate matcher.

Switched to Array.some to match the OR semantics, and updated the tests (partial-overlap, single-overlap, no-overlap, empty-array). The sibling isMatching*Filter helpers were checked — this is the only affected one.

Review in cubic

The in-memory isMatchingMultiSelectFilter evaluated the containsAny
operand with Array.every, which required a record to hold *all* of the
selected options. The operand means "contains any", and the server runs
it as a Postgres array-overlap (field::text[] && ARRAY[...]), i.e. a
record matches when it shares at least one option.

Because of every(), the client-side matcher disagreed with the server:
records that overlap on some (but not all) options were treated as
non-matching. This surfaces in optimistic cache updates
(isRecordMatchingFilter) where a created/edited record that should join
a "contains any" view was dropped until a refetch, and it also feeds the
row-level-permission predicate matcher on the server.

Switch to Array.some so the matcher mirrors the overlap semantics, and
update the tests (the previous cases asserted the all-options behavior).
@twenty-ci-bot-public

Copy link
Copy Markdown

👋 Thanks for contributing to Twenty! We're excited to have you on board.

Your PR has been set to draft while you work on it. Once you're done, mark it as Ready for review and our automated checks will run.

By submitting your Pull Request, you acknowledge that you agree with the terms of our Contributor License Agreement.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Re-trigger cubic

@twenty-ci-bot-public

twenty-ci-bot-public Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

🔍 Visual Regression Review — twenty-ui

✅ No visual changes to review.

Changed: 0 · Added: 0 · Removed: 0 · Unchanged: 235


View run details · advisory mode

@twenty-ci-bot-public

twenty-ci-bot-public Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

🔍 Visual Regression Review — twenty-front

✅ 1 visual change(s) reviewed — all explained by this PR.

Changed: 2 · Added: 0 · Removed: 0 · Unchanged: 702

1 item(s) to double-check (uncertain / low confidence)
Story Verdict Confidence Explained by
🟡 modules-settings-playground-graphqlplayground--default uncertain 80% No connection — PR only modifies packages/twenty-shared/src/utils/filter/utils/i…
Changed stories
Story Diff %
modules-settings-playground-graphqlplayground--default 3%
modules-settings-playground-settingsmcpsetup--default 0%

View run details · advisory mode

@etiennejouan etiennejouan left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @winklemad thank you for your contribution. It works well. Please fix CI before I can approve your PR.

@twenty-ci-bot-public

Copy link
Copy Markdown

🔍 Automated Pre-Review

✅ No issues detected - This PR is ready for human review.


🧭 External PR Quality Review

🟠 Needs triage for the following reason(s):

  • Not associated with an existing issue (required for external PRs)

Checks

  • ⏳ CI: pending

Detailed findings (duplicate candidates, standards notes, summary) are in the workflow run logs.


View details

Automated pre-review — human approval still required.

@etiennejouan etiennejouan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@etiennejouan
etiennejouan merged commit 8b0e7a9 into twentyhq:main Jul 21, 2026
145 of 146 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants