Skip to content

Fixes #31980: handle null persona customization pages - #31981

Open
harshach wants to merge 2 commits into
mainfrom
harshach/debug-2-0-upgrade-error
Open

Fixes #31980: handle null persona customization pages#31981
harshach wants to merge 2 commits into
mainfrom
harshach/debug-2-0-upgrade-error

Conversation

@harshach

@harshach harshach commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Describe your changes:

Fixes #31980

I made persona customization reads, caches, stores, and writes tolerant of invalid legacy page entries because documents migrated from 1.13.3 to 2.0.0 can contain null, crashing Data Marketplace and My Data or allowing new null entries to be persisted.

Type of change:

  • Bug fix

High-level design:

  • Central runtime validation and immutable normalization before persona documents enter the shared React Query cache
  • Defensive page lookup across Data Marketplace, My Data, useCustomPages, and the customization store
  • Safe page updates that skip undefined resets and normalize every server response before updating either cache
  • Backward-compatible rollout with no database or schema migration required; existing null entries are ignored and new ones are no longer produced

Tests:

Use cases covered

  • Migrated persona document containing a null page renders Data Marketplace's default layout
  • My Data resolves a customized page after a null legacy entry
  • My Data falls back to its default layout when a Landing Page layout is missing or malformed
  • Shared React Query cache never retains invalid page entries
  • Resetting an unsaved layout does not persist an undefined/null page
  • Persona page add, replace, remove, normalization, immutability, and no-op behavior

Unit tests

  • I added unit and component tests for the new/changed logic.
  • Files added/updated: PersonaPage.utils.test.ts, useCustomPages.test.ts, DataMarketplacePage.component.test.tsx, MyDataPage.test.tsx, and CustomizablePage.test.tsx
  • Coverage: not separately measured; 38 focused tests pass across five suites

Backend integration tests

  • Not applicable (no backend API changes).

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • Not added; the migrated API payload and affected screens are covered by component and hook regressions.

Manual testing performed

  • Not performed; the exact migrated DocStore response shape is exercised by automated regressions.

UI screen recording / screenshots:

Not attached; the before-upgrade failure and reproducible payload are documented in #31980, and the corrected behavior is covered by component tests.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • My PR is linked to a GitHub issue via Fixes #<issue-number> above.
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.
  • For UI changes: I attached a screen recording and/or screenshots above.
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.
  • I have added a test that covers the exact scenario we are fixing.

Greptile Summary

The PR normalizes legacy persona customization documents before caching or storing them and adds defensive page lookup and update helpers. One malformed-layout path remains in the persona customization editor.

  • Filters null and structurally rejected page entries from shared persona documents
  • Normalizes mutation responses before synchronizing Zustand and React Query state
  • Adds defensive defaults and regressions for Data Marketplace, My Data, and reset behavior

Confidence Score: 4/5

The PR is not yet safe to merge because a malformed legacy landing-page layout can still crash the persona customization editor.

Central normalization retains pages whose layout is a truthy non-array value, allowing the customization editor to pass that value into layout utilities that invoke filter on it.

Files Needing Attention: openmetadata-ui/src/main/resources/ui/src/utils/CustomizePage/PersonaPage.utils.ts, openmetadata-ui/src/main/resources/ui/src/pages/CustomizablePage/CustomizeStore.ts

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/src/utils/CustomizePage/PersonaPage.utils.ts Adds centralized immutable page normalization and updates, but the predicate still retains pages with malformed required layout data.
openmetadata-ui/src/main/resources/ui/src/pages/CustomizablePage/CustomizablePage.tsx Uses immutable page updates and normalizes saved responses before synchronizing both client caches.
openmetadata-ui/src/main/resources/ui/src/pages/CustomizablePage/CustomizeStore.ts Normalizes documents on store entry, although retained malformed pages can still become the editor's current page.
openmetadata-ui/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx Safely defaults when a customized landing-page layout is absent or not an array.
openmetadata-ui/src/main/resources/ui/src/rest/queries/docStoreQuery.ts Normalizes persona documents before they enter the shared React Query cache.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Fetch persona document] --> B[normalizePersonaDocument]
  B --> C[React Query cache]
  B --> D[CustomizeStore]
  C --> E[My Data and Marketplace]
  D --> F[CustomizeMyData editor]
  F --> G[Landing-page layout utilities]
Loading

Reviews (2): Last reviewed commit: "fix(ui): validate My Data customized lay..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used:

Copilot AI lite review requested due to automatic review settings August 24, 2026 17:29
@github-actions github-actions Bot added backend safe to test Add this label to run secure Github workflows on PRs labels Aug 24, 2026

Copilot AI 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.

Pull request overview

This PR fixes a UI crash when persona UI customization documents migrated from 1.13.3 → 2.0.0 contain invalid legacy pages entries (notably null). It centralizes runtime validation/normalization at the shared React Query boundary and updates key consumers/writers to safely read and update persona pages without persisting new invalid entries.

Changes:

  • Added shared persona-page utilities to (a) safely lookup pages and (b) normalize documents by filtering invalid page entries.
  • Normalized persona documents in the shared DocStore React Query function so invalid pages entries never enter the cache.
  • Updated Data Marketplace, My Data, customization store, and hook consumers to use the defensive page lookup, plus added targeted unit/component tests for migrated legacy payloads and reset behavior.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
openmetadata-ui/src/main/resources/ui/src/utils/CustomizePage/PersonaPage.utils.ts Introduces safe page lookup (getPersonaPage), normalization (normalizePersonaDocument), and safe page updates (updatePersonaDocumentPage).
openmetadata-ui/src/main/resources/ui/src/utils/CustomizePage/PersonaPage.utils.test.ts Adds focused unit tests covering invalid legacy entries, immutability, and page add/replace/remove behavior.
openmetadata-ui/src/main/resources/ui/src/rest/queries/docStoreQuery.ts Normalizes persona documents at the shared React Query fetch boundary to keep cache entries clean.
openmetadata-ui/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx Uses defensive page lookup to avoid null dereferences for LandingPage customization reads.
openmetadata-ui/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.test.tsx Adds regression test ensuring My Data renders with a legacy null page entry present.
openmetadata-ui/src/main/resources/ui/src/pages/DataMarketplacePage/DataMarketplacePage.component.tsx Uses defensive page lookup to avoid null dereferences for Data Marketplace customization reads.
openmetadata-ui/src/main/resources/ui/src/pages/DataMarketplacePage/DataMarketplacePage.component.test.tsx Adds regression test ensuring default layout renders when legacy null page exists.
openmetadata-ui/src/main/resources/ui/src/pages/CustomizablePage/CustomizeStore.ts Normalizes documents entering the store and uses shared helpers for reads/writes to avoid invalid pages.
openmetadata-ui/src/main/resources/ui/src/pages/CustomizablePage/CustomizablePage.tsx Uses shared update + normalization helpers to prevent persisting undefined/null pages and to sync normalized responses into cache/store.
openmetadata-ui/src/main/resources/ui/src/pages/CustomizablePage/CustomizablePage.test.tsx Adds regression test ensuring “reset unsaved layout” does not persist an undefined/null page.
openmetadata-ui/src/main/resources/ui/src/hooks/useCustomPages.ts Switches to shared defensive page lookup for consistent null-safe reads.
openmetadata-ui/src/main/resources/ui/src/hooks/useCustomPages.test.ts Adds regression validating that cached persona documents are normalized (null pages removed).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

chirag-madlani
chirag-madlani previously approved these changes Aug 24, 2026
@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 67%
67.09% (80486/119957) 51.51% (49278/95649) 52.46% (14717/28049)

Copilot AI review requested due to automatic review settings August 24, 2026 17:55
@gitar-bot

gitar-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Adds defensive validation and normalization for persona customization pages to gracefully handle null legacy entries from migrations. No issues found.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@harshach harshach added the To release Will cherry-pick this PR into the release branch label Aug 24, 2026
Comment on lines +23 to +26
const isPersonaPage = (value: unknown): value is Page =>
typeof value === 'object' &&
value !== null &&
typeof (value as { pageType?: unknown }).pageType === 'string';

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.

P1 Malformed layout crashes customization editor

If a legacy LandingPage entry has a string pageType but a truthy non-array layout, isPersonaPage retains it and the customization store passes it to the landing-page layout utilities, where layout.filter throws and crashes the persona customization editor.

Knowledge Base Used:

Copilot AI 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.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

openmetadata-ui/src/main/resources/ui/src/pages/CustomizablePage/CustomizablePage.tsx:110

  • syncSavedDocument writes to React Query using docStoreQueryKey(document?.fullyQualifiedName ?? ''), which can be stale (closure) and can produce a cache entry for an empty FQN if document is ever null/undefined at call time. Since the server response includes the authoritative fullyQualifiedName, key the cache update off normalizedResponse.fullyQualifiedName instead.
  const syncSavedDocument = (response: Document) => {
    const normalizedResponse = normalizePersonaDocument(response);

    setDocument(normalizedResponse);
    queryClient.setQueryData(
      docStoreQueryKey(document?.fullyQualifiedName ?? ''),
      normalizedResponse
    );

openmetadata-ui/src/main/resources/ui/src/pages/CustomizablePage/CustomizeStore.ts:55

  • setDocument can be called when currentPageType is still null (e.g., CustomizablePage initializes the store with setDocument(pageData) before setCurrentPageType(...)). The current implementation then forces ({ pageType: currentPageType } as Page), which can put an invalid pageType: null into state and cause downstream code to assume a valid PageType string. Guard the update so currentPage is only set when currentPageType is available.
  setDocument: (document: Document) => {
    const { updateCurrentPage, currentPageType } = get();
    const normalizedDocument = normalizePersonaDocument(document);
    const newPage = getPersonaPage(normalizedDocument, currentPageType);

    updateCurrentPage(newPage ?? ({ pageType: currentPageType } as Page));

    set({ document: normalizedDocument });

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit 715fdc2a53dd855a3dd3d7e5d33708f01dfbf3f9 in Playwright run 32759413240, attempt 1.

✅ 553 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky

Performance

Blocking targets: ✅ met · Optimization targets: 🟡 in progress

Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting.

🕒 Full workflow signal wall (to summary) 58m 53s

⏱️ Max setup 5m 14s · max shard execution 16m 21s · max shard-job elapsed before upload 20m 58s · reporting 5s

🌐 215.84 requests/attempt · 2.83 app boots/UI scenario · 41.90% common-shard skew

Optimization targets still in progress:

  • Common shard skew was 41.9% (convergence target: at most 15%).
  • Browser traffic was 215.84 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 2.83 per UI scenario (1623 boots / 574 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
✅ Shard chromium-01 105 0 0 0 0 0
✅ Shard chromium-02 104 0 0 0 0 0
✅ Shard chromium-03 87 0 0 0 0 0
✅ Shard chromium-04 103 0 0 0 0 0
✅ Shard data-asset-rules-01 61 0 0 0 0 0
✅ Shard domain-isolation-01 16 0 0 0 0 0
✅ Shard global-state-01 34 0 0 0 0 0
✅ Shard ingestion-01 1 0 0 0 0 0
✅ Shard reindex-01 2 0 0 0 0 0
✅ Shard search-01 11 0 0 0 0 0
✅ Shard search-rbac-01 29 0 0 0 0 0

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

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

Labels

backend safe to test Add this label to run secure Github workflows on PRs To release Will cherry-pick this PR into the release branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UI crashes on migrated persona documents with null pages

3 participants