Skip to content

fix(ui): preserve TagLabel server fields when saving tags (#28038)#28105

Merged
siddhant1 merged 2 commits into
mainfrom
sid/fix-28038-tag-applied-by
May 15, 2026
Merged

fix(ui): preserve TagLabel server fields when saving tags (#28038)#28105
siddhant1 merged 2 commits into
mainfrom
sid/fix-28038-tag-applied-by

Conversation

@siddhant1
Copy link
Copy Markdown
Member

@siddhant1 siddhant1 commented May 14, 2026

Summary

  • Fix TagsContainerV2.handleSave to pass every TagLabel schema field on the option payload through to the PATCH, so server-managed fields (appliedBy, appliedAt, metadata, reason) survive the JSON-Patch diff.
  • Closes Error while updating GlossaryTerms – Non-existing name/value pair in the object for key appliedBy #28038. The user-visible symptom was 500 Non-existing name/value pair in the object for key appliedBy when adding one tag and removing another in the same save. The underlying cause was that the UI silently wiped appliedBy/appliedAt on every save: handleSave rebuilt each tag from an 8-field allowlist that pre-dated those fields being added to the schema in Tagging explanation #24817. fast-json-patch.compare(old, new) then emitted remove /tags/N/appliedBy ops the UI never intended; the backend correctly refused them when the path no longer existed at apply time.

A future PR adding another optional field to TagLabel would re-introduce the same class of bug. To prevent that:

  • The new Jest test (passes every TagLabel schema field through to onSelectionChange) builds a Required<TagLabel> fixture. Adding a new field to the schema means the fixture won't compile until it's populated; once it is, the assertion loop catches a handleSave that doesn't pass it through.
  • The Playwright test seeds two tags via API, drives the UI to keep one and swap the other, and asserts that the surviving tag's appliedBy matches the server-populated value before the edit. Together with the PATCH status check, this covers both halves of the bug: no 500 and no silent data loss.

Test plan

  • yarn test src/components/Tag/TagsContainerV2/TagsContainerV2.test.tsx — 3/3 pass
  • yarn ui-checkstyle:changed on the touched src files — clean
  • yarn ui-checkstyle:playwright:changed playwright/e2e/Pages/Tags.spec.ts — clean
  • npx tsc --noEmit — no errors on changed files
  • Playwright E2E (Adds one tag and removes another in the same save preserves appliedBy on the kept tag) — passes against yarn start (Vite dev server on :3000 with the live code). Test verifies (a) PATCH returns 200 and (b) the kept tag's appliedBy matches the pre-edit server-populated value.
  • Manual repro on a fully built stack: add+remove tags in the same save returns 200, and the kept tag's appliedBy is intact via API.

TagsContainerV2.handleSave rebuilt each tag from an 8-field allowlist
that silently dropped appliedBy, appliedAt, metadata, and reason — added
to the TagLabel schema in #24817. The resulting JSON-Patch diff emitted
spurious `remove /tags/N/appliedBy` ops, which the backend rejected with
500 when the path no longer existed at apply time (closes #28038).

Pass every TagLabel schema field on the option payload through to the
PATCH so server-managed fields survive the diff. The Jest schema-coverage
test uses `Required<TagLabel>` so adding a new field to tagLabel.json
forces the test fixture and assertion to cover it, preventing the same
class of bug from recurring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 14, 2026 06:13
@siddhant1 siddhant1 requested a review from a team as a code owner May 14, 2026 06:13
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

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

This PR fixes tag saving in the UI so TagLabel server-managed fields are preserved when tags are edited, preventing unintended JSON Patch removals and related backend failures.

Changes:

  • Preserves all current TagLabel fields in TagsContainerV2.handleSave.
  • Adds Jest coverage for preserving applied fields and full TagLabel pass-through.
  • Adds Playwright regression coverage for add-one/remove-one tag saves preserving appliedBy.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx Updates tag save payload construction to retain server-managed fields.
openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.test.tsx Adds unit tests for preserving TagLabel fields during save.
openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Tags.spec.ts Adds E2E regression test for simultaneous tag add/remove behavior.

The two `as` casts those imports backed were removed; TypeScript inference
covers the remaining flow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@siddhant1 siddhant1 added UI UI specific issues safe to test Add this label to run secure Github workflows on PRs To release Will cherry-pick this PR into the release branch labels May 14, 2026
@gitar-bot
Copy link
Copy Markdown

gitar-bot Bot commented May 14, 2026

Code Review ✅ Approved

Preserves TagLabel server-managed fields like appliedBy and appliedAt during UI save operations by removing the restrictive allowlist. Verified through new Jest fixtures and Playwright E2E tests to prevent future data loss regressions.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@github-actions
Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 62%
62.46% (64659/103514) 43.15% (35171/81502) 45.95% (10353/22528)

@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

🟡 Playwright Results — all passed (15 flaky)

✅ 4071 passed · ❌ 0 failed · 🟡 15 flaky · ⏭️ 86 skipped

Shard Passed Failed Flaky Skipped
✅ Shard 1 299 0 0 4
🟡 Shard 2 759 0 9 8
🟡 Shard 3 779 0 2 7
🟡 Shard 4 789 0 1 18
✅ Shard 5 709 0 0 41
🟡 Shard 6 736 0 3 8
🟡 15 flaky test(s) (passed on retry)
  • Features/ActivityAPI.spec.ts › Activity event shows the actor who made the change (shard 2, 1 retry)
  • Features/BulkEditEntity.spec.ts › Glossary (shard 2, 1 retry)
  • Features/DataProductDomainMigration.spec.ts › Data product with no assets can change domain without confirmation (shard 2, 1 retry)
  • Features/DomainFilterQueryFilter.spec.ts › Quick filters should persist when domain filter is applied and cleared (shard 2, 1 retry)
  • Features/Glossary/GlossaryWorkflow.spec.ts › should start term as Draft when glossary has reviewers (shard 2, 2 retries)
  • Features/KnowledgeCenter.spec.ts › Article mentions in description should working for Knowledge Center (shard 2, 1 retry)
  • Features/KnowledgeCenterTextEditor.spec.ts › Rich Text Editor - Text Formatting (shard 2, 1 retry)
  • Features/KnowledgeCenterTextEditor.spec.ts › Rich Text Editor - Text Formatting (shard 2, 1 retry)
  • Features/KnowledgeCenterTextEditor.spec.ts › Rich Text Editor - Text Formatting (shard 2, 1 retry)
  • Features/RTL.spec.ts › Verify Following widget functionality (shard 3, 1 retry)
  • Flow/NotificationAlerts.spec.ts › Alert operations for a user with and without permissions (shard 3, 1 retry)
  • Pages/DataContractsSemanticRules.spec.ts › Validate Description Rule Is_Set (shard 4, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/ODCSImportExport.spec.ts › Multi-object ODCS contract - object selector shows all schema objects (shard 6, 1 retry)
  • Pages/UserDetails.spec.ts › Create team with domain and verify visibility of inherited domain in user profile after team removal (shard 6, 1 retry)

📦 Download artifacts

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

@siddhant1 siddhant1 merged commit bba0bf8 into main May 15, 2026
70 of 105 checks passed
@siddhant1 siddhant1 deleted the sid/fix-28038-tag-applied-by branch May 15, 2026 05:27
@github-actions
Copy link
Copy Markdown
Contributor

Changes have been cherry-picked to the 1.12.9 branch.

github-actions Bot pushed a commit that referenced this pull request May 15, 2026
…28105)

* fix(ui): preserve TagLabel server fields when saving tags

TagsContainerV2.handleSave rebuilt each tag from an 8-field allowlist
that silently dropped appliedBy, appliedAt, metadata, and reason — added
to the TagLabel schema in #24817. The resulting JSON-Patch diff emitted
spurious `remove /tags/N/appliedBy` ops, which the backend rejected with
500 when the path no longer existed at apply time (closes #28038).

Pass every TagLabel schema field on the option payload through to the
PATCH so server-managed fields survive the diff. The Jest schema-coverage
test uses `Required<TagLabel>` so adding a new field to tagLabel.json
forces the test fixture and assertion to cover it, preventing the same
class of bug from recurring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(ui): drop unused TagLabel/EntityTags imports from TagsContainerV2

The two `as` casts those imports backed were removed; TypeScript inference
covers the remaining flow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Siddhant <siddhant@MacBook-Pro-751.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit bba0bf8)
@github-actions
Copy link
Copy Markdown
Contributor

Changes have been cherry-picked to the 1.13 branch.

github-actions Bot pushed a commit that referenced this pull request May 15, 2026
…28105)

* fix(ui): preserve TagLabel server fields when saving tags

TagsContainerV2.handleSave rebuilt each tag from an 8-field allowlist
that silently dropped appliedBy, appliedAt, metadata, and reason — added
to the TagLabel schema in #24817. The resulting JSON-Patch diff emitted
spurious `remove /tags/N/appliedBy` ops, which the backend rejected with
500 when the path no longer existed at apply time (closes #28038).

Pass every TagLabel schema field on the option payload through to the
PATCH so server-managed fields survive the diff. The Jest schema-coverage
test uses `Required<TagLabel>` so adding a new field to tagLabel.json
forces the test fixture and assertion to cover it, preventing the same
class of bug from recurring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(ui): drop unused TagLabel/EntityTags imports from TagsContainerV2

The two `as` casts those imports backed were removed; TypeScript inference
covers the remaining flow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Siddhant <siddhant@MacBook-Pro-751.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit bba0bf8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error while updating GlossaryTerms – Non-existing name/value pair in the object for key appliedBy

3 participants