Skip to content

[WC-3520]: Gallery recover from stale sort-order attribute id - #2372

Open
yordan-st wants to merge 1 commit into
mainfrom
fix/WC-3520_sort-order-invalid-attribute
Open

[WC-3520]: Gallery recover from stale sort-order attribute id#2372
yordan-st wants to merge 1 commit into
mainfrom
fix/WC-3520_sort-order-invalid-attribute

Conversation

@yordan-st

Copy link
Copy Markdown
Contributor

Pull request type

Bug fix (non-breaking change which fixes an issue)


Description

Gallery crashed with an uncaught MobX reaction error — Sort order item: invalid attribute id '<id>' — when a sort order restored from datasource.sortOrder referenced an attribute id no longer valid in the current app build. Mendix attribute ids are per-build tokens regenerated on redeploy, so a sort order persisted per-user (personalization attribute / DB storage) can outlive the ids it references.

QueryParamsService now guards the forwarding of sort order into ListValue.setSortOrder(): on a runtime rejection it catches the error, falls back to the default (unsorted) order, and emits a console.warn so the reset is diagnosable. The guard sits on the shared forwarding path (the sort reaction), so it protects the widget whether or not a sort widget is configured — the SortOrderStore is not instantiated when no DropdownSort exists, which is why the fix is not there.

Ticket: WC-3520

What should be covered while testing?

  1. Configure a Gallery with sort personalization stored in a per-user attribute (DB storage).
  2. Sort the gallery, then redeploy the app so attribute ids regenerate (stale stored sort order).
  3. Re-run and open the page as the same user.
    • Before fix: widget crashes with invalid attribute id uncaught reaction error.
    • After fix: widget renders, falls back to default sort order, console.warn logged.
  4. Confirm the normal case (all-valid sort ids) still applies sort order unchanged, preserving order and direction.

@yordan-st
yordan-st marked this pull request as ready for review August 6, 2026 14:00
@yordan-st
yordan-st requested a review from a team as a code owner August 6, 2026 14:00
@yordan-st
yordan-st force-pushed the fix/WC-3520_sort-order-invalid-attribute branch from b0c433e to b00dec8 Compare August 6, 2026 14:00
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

AI Code Review

⚠️ Approved with suggestions — low-severity items only, safe to merge


What was reviewed

File Change
packages/pluggableWidgets/gallery-web/src/model/services/QueryParams.service.ts applySortOrder guard: try/catch around setSortOrder, fallback to undefined on rejection
packages/pluggableWidgets/gallery-web/src/model/services/__tests__/QueryParams.service.spec.ts New regression test file — 3 tests covering happy path, reaction-error path, and fallback recovery
packages/pluggableWidgets/gallery-web/CHANGELOG.md User-facing fix entry under [Unreleased]
packages/pluggableWidgets/gallery-web/openspec/changes/fix-stale-sort-order-attribute/ OpenSpec artifacts (design, proposal, spec, tasks) — documentation only

Skipped (out of scope): dist/, pnpm-lock.yaml, OpenSpec YAML frontmatter

All CI checks could not be retrieved (approval required) — please verify green before merge.


Findings

⚠️ Low — Missing stop() call in third test leaks reactions

File: packages/pluggableWidgets/gallery-web/src/model/services/__tests__/QueryParams.service.spec.ts line 104

Note: start() returns a disposer function, but the third test doesn't capture or call it. The two MobX reactions (sort + filter) remain active after the test ends. Jest isolates module state per file so this won't pollute other test files, but it can trigger "active reactions remain after test" warnings and will accumulate cleanup overhead across the suite.

Fix:

it("recovers to default sort when an invalid id is encountered", () => {
    // ...
    const { host, start } = testHost();
    new QueryParamsService(host, query, filters, sort);
    const stop = start(); // capture the disposer

    expect(query.applied.at(-1)).toEqual(undefined);
    stop(); // dispose reactions
});

Positives

  • Using onReactionError to assert no MobX reaction exception is the correct approach — a plain expect(...).not.toThrow() gives a false green because MobX swallows reaction exceptions internally. The test comment explaining this is genuinely useful.
  • Fix is placed at the right choke point (QueryParamsService sort reaction) rather than in SortOrderStore, which would have missed the no-sort-widget configuration. The design doc traces this reasoning clearly.
  • The source comment explaining attribute-id regeneration on redeploy and the WC-3520 reference is appropriate — this is a non-obvious Mendix runtime behaviour that a future reader would otherwise have to rediscover.
  • CHANGELOG entry uses user-facing language (describes the visible crash symptom and recovery behaviour) with no implementation details leaking through.
  • attrId() from @mendix/widget-plugin-test-utils is used for attribute IDs rather than hand-rolling strings, keeping the stub aligned with builder patterns.

@iobuhov iobuhov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM


This guard SHALL apply on the path every sort order takes into the datasource, regardless of whether a sort widget (DropdownSort) is configured — i.e. it SHALL NOT depend on a `SortOrderStore` being instantiated.

#### Scenario: Restored sort order contains a stale attribute id

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is it really the case that framework is supplying us with outdated sorting information? We have to let the framework team know so they can fix it us well. Can you confirm this is the case and create a trivial reproduction code for it?

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.

3 participants