Skip to content

fix(explore): add matrixify_enable guard to prevent stale validators on pre-revamp charts#38765

Open
sadpandajoe wants to merge 7 commits intomasterfrom
fix-echart-save-issue
Open

fix(explore): add matrixify_enable guard to prevent stale validators on pre-revamp charts#38765
sadpandajoe wants to merge 7 commits intomasterfrom
fix-echart-save-issue

Conversation

@sadpandajoe
Copy link
Copy Markdown
Member

@sadpandajoe sadpandajoe commented Mar 20, 2026

User description

SUMMARY

Some charts are failing to load in explore view as well as the Save/Update buttons are disabled and the initial query is blocked by invisible validation errors.

Root cause: isMatrixifyVisible() evaluates mode values (matrixify_mode_rows/matrixify_mode_columns) without first checking whether matrixify is enabled (matrixify_enable). Pre-revamp charts have stale mode defaults ('dimensions'/'metrics') persisted in form_data, so isMatrixifyVisible() returns true and validators fire on empty matrixify controls. The errors are invisible because matrixify tab controls are excluded from the error banner.

Fix (3 parts):

  1. Runtime guard (matrixifyControls.tsx): isMatrixifyVisible() now checks matrixify_enable === true before evaluating mode values. Handles undefined (old charts) via !== true.

  2. Form_data migration (store.ts): handleDeprecatedControls() normalizes stale matrixify modes on legacy charts. Detects old per-axis enable flags (matrixify_enable_vertical_layout / matrixify_enable_horizontal_layout) to preserve modes for charts that genuinely used matrixify. Required because 4 downstream UI consumers (ExploreChartPanel, ChartContextMenu, DrillBySubmenu, ChartRenderer) infer "matrixify is active" from mode values alone.

  3. Dashboard + explore consistency (hydrateExplore.ts, store.ts): handleDeprecatedControls exported and called in hydrateExplore and applyDefaultFormData so both explore and dashboard paths normalize stale form_data.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A — logic-only fix with no UI changes.

TESTING INSTRUCTIONS

  1. Open a chart that was saved before the matrixify revamp (any chart without matrixify_enable in its form_data)
  2. Verify the chart loads and queries without errors
  3. Verify the Save/Update buttons are enabled
  4. Even with the Matrixify feature flag disabled, confirm that charts no longer hit hidden validation errors (control definitions and validators are registered regardless of the feature flag)
  5. Open a chart that uses matrixify (matrixify_enable: true) — verify matrixify controls still work correctly
  6. Open a pre-revamp chart on a dashboard — verify it renders without issues

Automated tests (34 total):

  • matrixifyControls.test.tsx (15 tests): Direct isMatrixifyVisible guard tests + validator injection via real mapStateToProps
  • store.test.tsx (19 tests): Migration, dashboard hydration, old per-axis flag detection, round-trip validation

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

CodeAnt-AI Description

Fix stale Matrixify settings so saved charts load and save normally

What Changed

  • Charts saved before the Matrixify change now ignore old Matrixify defaults unless Matrixify is actually enabled, preventing hidden validation errors from blocking load and save.
  • Legacy charts that used the older per-axis Matrixify settings are now carried forward correctly, keeping active Matrixify layouts working while resetting unused sides.
  • Dashboard and Explore both apply the same cleanup so chart settings stay consistent across entry points.
  • Added tests for hidden validation behavior, legacy setting cleanup, and dashboard hydration paths.

Impact

✅ Fewer blocked chart saves
✅ Fewer chart load failures for older saved charts
✅ Consistent Matrixify behavior in Explore and dashboards

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review bot commented Mar 20, 2026

Code Review Agent Run #b767fe

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset-frontend/packages/superset-ui-chart-controls/test/shared-controls/matrixifyControls.test.tsx - 1
    • Missing return type hints · Line 37-50
      Helper functions buildControls and buildState lack explicit return type hints, which violates the codebase's type safety standards requiring explicit annotations for all functions, including test helpers. This improves consistency and enables better static checking without changing behavior.
      Code suggestion
       @@ -37,1 +37,1 @@
      - const buildControls = (overrides: Record<string, any> = {}) => {
      + const buildControls = (overrides: Record<string, any> = {}): Record<string, { value: any }> => {
       @@ -47,4 +47,4 @@
      - const buildState = (
      -   controlValues: Record<string, any> = {},
      -   formData: Record<string, any> = {},
      - ) =>
      + const buildState = (
      +   controlValues: Record<string, any> = {},
      +   formData: Record<string, any> = {},
      + ): ControlPanelState =>
Review Details
  • Files reviewed - 5 · Commit Range: d307100..88a9b3b
    • superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/matrixifyControls.tsx
    • superset-frontend/packages/superset-ui-chart-controls/test/shared-controls/matrixifyControls.test.tsx
    • superset-frontend/src/explore/actions/hydrateExplore.ts
    • superset-frontend/src/explore/store.test.tsx
    • superset-frontend/src/explore/store.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@dosubot dosubot bot added the explore Namespace | Anything related to Explore label Mar 20, 2026
@codeant-ai-for-open-source codeant-ai-for-open-source bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Mar 20, 2026
@codeant-ai-for-open-source
Copy link
Copy Markdown
Contributor

Sequence Diagram

This PR fixes legacy chart loading by normalizing stale matrixify fields before control state is built, and by gating matrixify visibility on an explicit enable flag. Together, these changes prevent hidden validators from blocking initial queries and save actions.

sequenceDiagram
    participant User
    participant ExploreOrDashboard
    participant Store
    participant MatrixifyControls
    participant UI

    User->>ExploreOrDashboard: Open legacy chart
    ExploreOrDashboard->>Store: Normalize deprecated form data
    Store->>Store: If enable missing migrate old flags or disable stale modes
    ExploreOrDashboard->>MatrixifyControls: Build controls from normalized form data
    MatrixifyControls->>MatrixifyControls: Require matrixify enable true before mode checks
    MatrixifyControls-->>UI: No hidden matrixify validators
    UI-->>User: Chart loads and save update stays enabled
Loading

Generated by CodeAnt AI

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 20, 2026

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 9fcf6d8
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/69c6ad00f77bb00009c71f51
😎 Deploy Preview https://deploy-preview-38765--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a regression where legacy (pre-matrixify-revamp) charts can end up with hidden matrixify validation errors in Explore due to stale persisted matrixify_mode_* values, and normalizes legacy matrixify-related form_data during Explore and dashboard hydration.

Changes:

  • Guard isMatrixifyVisible() behind matrixify_enable === true to prevent invisible validators from firing on legacy charts.
  • Add handleDeprecatedControls() migration logic to normalize legacy matrixify fields (including old per-axis enable flags) and apply it consistently across Explore + dashboard hydration paths.
  • Add/expand unit tests covering the guard behavior, validator injection, and form_data normalization.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
superset-frontend/src/explore/store.ts Exports and extends deprecated-control normalization to migrate/reset legacy matrixify fields; applies normalization in applyDefaultFormData.
superset-frontend/src/explore/store.test.tsx Adds regression tests for legacy matrixify normalization across Explore and dashboard paths.
superset-frontend/src/explore/actions/hydrateExplore.ts Runs deprecated-control normalization before storing initial form_data in Redux state.
superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/matrixifyControls.tsx Adds matrixify_enable guard in isMatrixifyVisible() and exports it for testing.
superset-frontend/packages/superset-ui-chart-controls/test/shared-controls/matrixifyControls.test.tsx New tests for visibility guard and validator injection behavior.

Comment on lines +122 to 127
// must reflect the same migration so the two stay consistent.
handleDeprecatedControls(initialFormData);

const initialExploreState = {
form_data: initialFormData,
slice: initialSlice,
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

hydrateExplore mutates initialFormData in place (now including handleDeprecatedControls(initialFormData)). When initialFormData is sourced from initialSlice?.form_data (from Redux state), this can mutate the sliceEntities cache/state object. Consider cloning (and possibly deep-cloning) the initial form_data before any in-place edits/migrations so Redux state isn't mutated indirectly.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Pre-existing pattern — lines 80–103 of this same function already mutate initialFormData in place (viz_type, time_range, groupby, granularity_sqla, dashboardId). Cloning just for this call would be inconsistent; fixing the broader mutation-of-Redux-state issue is out of scope for this bug fix.

Comment on lines +26 to +27
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).featureFlags = {};
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

This test file assigns window.featureFlags at module scope but doesn't restore the prior value. To avoid cross-test leakage when Jest reuses the same environment for multiple files, consider capturing the existing window.featureFlags in beforeAll/beforeEach and restoring it in afterAll/afterEach.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This follows the existing codebase pattern (e.g. ExploreChartHeader.test.tsx:43 does the same). Setting to an empty {} at module scope doesn't leak test-specific state between files.

Comment on lines +75 to +86
if (!('matrixify_enable' in formData)) {
const hadVerticalLayout =
formData.matrixify_enable_vertical_layout === true;
const hadHorizontalLayout =
formData.matrixify_enable_horizontal_layout === true;

if (hadVerticalLayout || hadHorizontalLayout) {
// Pre-revamp chart that genuinely used matrixify — migrate to new flag
formData.matrixify_enable = true;
if (!hadVerticalLayout) formData.matrixify_mode_rows = 'disabled';
if (!hadHorizontalLayout) formData.matrixify_mode_columns = 'disabled';
} else {
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

handleDeprecatedControls migrates legacy per-axis matrixify flags to the new matrixify_enable toggle, but it leaves the deprecated keys (matrixify_enable_vertical_layout / matrixify_enable_horizontal_layout) on formData. Because applyDefaultFormData later merges all keys from cleanedFormData, these deprecated fields can be carried forward and re-persisted. Consider deleting these deprecated properties after migration so the normalized form_data no longer contains removed controls.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Follows the existing convention in this function — the y_axis_zero migration (line 57–60) also leaves the deprecated key on formData after migrating its value. The old per-axis keys are dead data (no code reads them after the revamp), so leaving them is harmless and consistent.

@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review bot commented Mar 20, 2026

Code Review Agent Run #aea000

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 88a9b3b..ae79c1b
    • superset-frontend/src/explore/actions/hydrateExplore.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

// The matrixify_enable guard prevents hidden validators from firing on
// pre-revamp charts with stale matrixify_mode defaults (fix for #38519).
const isMatrixifyVisible = (
controls: any,
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.

Just a small NIT: controls is typed as any. Given that the function only accesses controls?.[key]?.value, a narrower type like Record<string, { value?: unknown } | undefined> or something like that would be sufficient.

This aligns with the project's ongoing removal of any
Not a blocker.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

nice callout. Done.

@github-actions github-actions bot added i18n Namespace | Anything related to localization i18n:italian Translation related to Italian language doc Namespace | Anything related to documentation plugins dependencies:npm labels Mar 24, 2026
@michael-s-molina
Copy link
Copy Markdown
Member

michael-s-molina commented Mar 24, 2026

@sadpandajoe @msyavuz Is this complementary or a duplicate of #38759?

@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review bot commented Mar 24, 2026

Code Review Agent Run #a9f5e3

Actionable Suggestions - 0
Review Details
  • Files reviewed - 5 · Commit Range: ae61a0c..570c05a
    • superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/matrixifyControls.tsx
    • superset-frontend/packages/superset-ui-chart-controls/test/shared-controls/matrixifyControls.test.tsx
    • superset-frontend/src/explore/actions/hydrateExplore.ts
    • superset-frontend/src/explore/store.test.tsx
    • superset-frontend/src/explore/store.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

The previous commit replaced `controls: any` with `ControlStateMapping`
in isMatrixifyVisible but left test helpers returning incompatible types,
breaking the tsc step in CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sadpandajoe
Copy link
Copy Markdown
Member Author

@sadpandajoe @msyavuz Is this complementary or a duplicate of #38759?

This should be complimentary

@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review bot commented Mar 24, 2026

Code Review Agent Run #250285

Actionable Suggestions - 0
Review Details
  • Files reviewed - 3 · Commit Range: 570c05a..5a194fd
    • superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/matrixifyControls.test.ts
    • superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/matrixifyControls.tsx
    • superset-frontend/packages/superset-ui-chart-controls/test/shared-controls/matrixifyControls.test.tsx
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@codeant-ai-for-open-source codeant-ai-for-open-source bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:XXL This PR changes 1000+ lines, ignoring generated files labels Mar 27, 2026
@sadpandajoe sadpandajoe added the hold:testing! On hold for testing label Mar 30, 2026
@sadpandajoe sadpandajoe added the 🎪 ⚡ showtime-trigger-start Create new ephemeral environment for this PR label Apr 12, 2026
@github-actions github-actions bot added 🎪 9fcf6d8 🚦 building Environment 9fcf6d8 status: building 🎪 9fcf6d8 📅 2026-04-12T03-54 Environment 9fcf6d8 created at 2026-04-12T03-54 🎪 9fcf6d8 🤡 sadpandajoe Environment 9fcf6d8 requested by sadpandajoe 🎪 ⌛ 48h Environment expires after 48 hours (default) and removed 🎪 ⚡ showtime-trigger-start Create new ephemeral environment for this PR labels Apr 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🎪 Showtime is building environment on GHA for 9fcf6d8

@github-actions github-actions bot added 🎪 9fcf6d8 🚦 deploying Environment 9fcf6d8 status: deploying 🎪 9fcf6d8 🚦 running Environment 9fcf6d8 status: running 🎪 🎯 9fcf6d8 Active environment pointer - 9fcf6d8 is receiving traffic 🎪 9fcf6d8 🌐 35.87.137.255:8080 Environment 9fcf6d8 URL: http://35.87.137.255:8080 (click to visit) and removed 🎪 9fcf6d8 🚦 building Environment 9fcf6d8 status: building 🎪 9fcf6d8 🚦 deploying Environment 9fcf6d8 status: deploying 🎪 9fcf6d8 🚦 running Environment 9fcf6d8 status: running 🎪 🎯 9fcf6d8 Active environment pointer - 9fcf6d8 is receiving traffic labels Apr 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🎪 Showtime deployed environment on GHA for 9fcf6d8

Environment: http://35.87.137.255:8080 (admin/admin)
Lifetime: 48h auto-cleanup
Updates: New commits create fresh environments automatically

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

explore Namespace | Anything related to Explore hold:testing! On hold for testing packages size/XL size:XL This PR changes 500-999 lines, ignoring generated files 🎪 9fcf6d8 🚦 running Environment 9fcf6d8 status: running 🎪 9fcf6d8 🤡 sadpandajoe Environment 9fcf6d8 requested by sadpandajoe 🎪 9fcf6d8 🌐 35.87.137.255:8080 Environment 9fcf6d8 URL: http://35.87.137.255:8080 (click to visit) 🎪 9fcf6d8 📅 2026-04-12T03-54 Environment 9fcf6d8 created at 2026-04-12T03-54 🎪 ⌛ 48h Environment expires after 48 hours (default)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants