Matrixify: dimension members are resolved at config time, ignore dashboard filters, and silently omit members that have data
- Dominant language
- Python
- Stars
- 74.8k
- Forks
- 18.3k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 685
Description
### Bug
With a Matrixify axis in `dimensions` mode, the member list is resolved in Explore and frozen into `form_data`. It is never re-resolved at render, so it cannot respond to dashboard filters — and in `all` mode it is truncated at a hardcoded 25. The result is that a matrixified chart **silently omits dimension members that have data under the viewer's active filters**.
Cell *contents* are filter-aware; cell *membership* is not. That is what makes this a correctness bug rather than a cosmetic one.
### Where membership is decided
`MatrixifyGridGenerator.ts` — one cell per member, before any query runs:
```js
rowCount = config.rows.dimension.values.length;
```
`MatrixifyDimensionControl.tsx` — the list is fetched by an **Explore control**, which never mounts on a dashboard:
```js
const MAX_ALL_DIMENSION_VALUES = 25;
const allValues = selectionMode === 'all'
? values.slice(0, MAX_ALL_DIMENSION_VALUES)
: value.values || [];
```
`members`/`all` call `/api/v1/datasource/{type}/{id}/column/{column}/values/` with no filters at all. Every mode writes its result into `form_data`, so it is identical for all viewers.
### Top N is not a workaround
Top N passes filters, but it runs at config time — before the render path — so it ranks members over the **whole dataset**, not per viewer. "Top" therefore doesn't mean "relevant to this viewer": the globally-largest member gets a guaranteed "No data" panel for someone with no rows for it, while that viewer's own most-active members can be missing entirely. Ranking globally and rendering per-viewer cannot be reconciled.
### Reproduce
1. Enable `MATRIXIFY`.
2. Dataset where one dimension has >25 distinct values (69 here), and a second dimension partitions rows so each of its values touches only a small subset of the first (projects vs. employees).
3. Chart matrixified by rows on the high-cardinality dimension, `All dimensions`, sorted by metric.
4. Dashboard with a single-select native filter on the second dimension; switch between values.
### Actual
69 members, 25 cap, on 6.1.0:
| viewer | panels populated | members **with data** omitted entirely |
|---|---|---|
| Employee A | 8 / 25 | 6 |
| Employee B | 4 / 25 | 1 |
Employee A has data for 14 members; 8 rendered, with no indication the other 6 existed. Alphabetical sorting fails identically on a different arbitrary subset. Since members exceed the cap, **no configuration of this chart is correct for all viewers.**
### Expected
Members resolved against the chart's effective filters (`form_data` + `extra_form_data`) at render time, so a member with data under the active filters is never dropped.
### Suggested fixes
1. **Resolve members in the render path** using effective filters — the actual fix.
2. **A "hide empty cells" option** — helps, but insufficient alone: the cap drops members before any query runs.
3. **Make `MAX_ALL_DIMENSION_VALUES` configurable** — hardcoded at 25, while `members` mode is uncapped.
4. **Surface truncation in the UI** when `totalValueCount` exceeds the cap; today it is silent.
### Environment
Superset 6.1.0 · Postgres metadata and analytics DB · `MATRIXIFY`, `ENABLE_TEMPLATE_PROCESSING`, `DASHBOARD_RBAC` · `echarts_timeseries_bar` with two saved metrics, matrixified by rows.
Related: #39007, #39008 — other 6.1 Matrixify defects; neither covers member resolution.
Contributor guide
Research direction
Start by tracing membership from MatrixifyDimensionControl.tsx and MatrixifyGridGenerator.ts, then follow the render path that receives form_data and extra_form_data. Verify the reproduction with filtered dashboard views and confirm that every member with data is represented without the 25-value omission.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- data-visualization, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100