Skip to content

fix: resolve client-side error when re-selecting newly created tag#3691

Open
MaanLad wants to merge 2 commits intodubinc:mainfrom
MaanLad:fix/tag-reselect-client-error
Open

fix: resolve client-side error when re-selecting newly created tag#3691
MaanLad wants to merge 2 commits intodubinc:mainfrom
MaanLad:fix/tag-reselect-client-error

Conversation

@MaanLad
Copy link
Copy Markdown

@MaanLad MaanLad commented Apr 4, 2026

Fix: Client-side error when re-selecting newly created tag

Summary

Fixes a client-side error that occurs when a newly created tag is unselected and then selected again.


Root Cause

  • State mismatch between tag-select and @dub/ui ComboBox
  • useTags mutation was updating both base and search queries, leading to inconsistent data

Changes

  • Updated mutation logic to only append the new tag to the base query (no search)
  • Prevented mutation of search-based queries to avoid stale or invalid state
await mutate(
  (key) => {
    if (typeof key !== "string") return false;
    if (!key.startsWith(`/api/tags?workspaceId=${workspaceId}`)) return false;
    if (!key.includes("search=")) return true;
    return key.includes("search=") && key.includes("search=&");
  },
  (data) => (data ? [newTag, ...data] : [newTag]),
  false
);

Behavior

  • Works correctly for local search (cached tags)
  • Works correctly for API search (after exceeding TAGS_MAX_PAGE_SIZE)

Result

Tags can now be re-selected without client-side errors.


Issue

Closes #3685

Summary by CodeRabbit

  • Bug Fixes
    • Improved tag creation responsiveness by ensuring newly created tags display immediately in the selector.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 4, 2026

@MaanLad is attempting to deploy a commit to the Dub Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 4, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 4, 2026

📝 Walkthrough

Walkthrough

The change improves cache synchronization after tag creation by implementing selective SWR cache updates. Instead of revalidating a single query key, it now targets all relevant tag query variants, properly revalidates base queries, strategically refreshes search-filtered queries, and prepends newly created tags into the cached data structure.

Changes

Cohort / File(s) Summary
Tag Cache Mutation Logic
apps/web/ui/links/link-builder/tag-select.tsx
Replaced single SWR cache revalidation with targeted mutation that filters keys by workspace, conditionally revalidates base and search-filtered queries, and prepends newly created tags to existing cached data or initializes new cache entries.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A tag was born, but lost in the cache,
Reselected twice—oh, what a clash!
Now keys are filtered, data's precise,
The newly-minted tag—prepended twice!
Cache synchronization, finally right,
Selection errors fade into the night! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: resolving a client-side error when re-selecting newly created tags, matching the primary change in the PR.
Linked Issues check ✅ Passed The PR implements the core fix from issue #3685 by updating the mutation logic to append new tags only to base queries and avoid mutating search-based queries, addressing the state inconsistency root cause.
Out of Scope Changes check ✅ Passed All changes in tag-select.tsx are directly related to fixing the cache mutation strategy for newly created tags as specified in issue #3685, with no unrelated modifications present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/web/ui/links/link-builder/tag-select.tsx (1)

80-89: Good approach for selective cache mutation; minor simplification possible.

The strategy to mutate only base queries (non-search keys and empty-search keys) while skipping active search queries is sound and aligns with the fix goals.

One minor redundancy: on line 85, since we only reach this line when key.includes("search=") is true (line 84 didn't return true), the first part of the condition is always satisfied. You could simplify to just return key.includes("search=&");.

🧹 Optional simplification
       await mutate(
         (key) => {
           if (typeof key !== "string") return false;
           if (!key.startsWith(`/api/tags?workspaceId=${workspaceId}`)) return false;
           if (!key.includes("search=")) return true;
-          return key.includes("search=") && key.includes("search=&"); // Only base query
+          return key.includes("search=&"); // Only base query (empty search)
         },
         (data) => (data ? [newTag, ...data] : [newTag]),
         false
       );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/ui/links/link-builder/tag-select.tsx` around lines 80 - 89, The
key-filtering predicate passed to mutate can be simplified: inside the mutate
call (the predicate that checks cache keys for
`/api/tags?workspaceId=${workspaceId}`) remove the redundant check and instead,
after ensuring key includes "search=", return only key.includes("search=&");
keep the surrounding checks for typeof key and
startsWith(`/api/tags?workspaceId=${workspaceId}`) and leave the updater that
prepends newTag unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/web/ui/links/link-builder/tag-select.tsx`:
- Around line 80-89: The key-filtering predicate passed to mutate can be
simplified: inside the mutate call (the predicate that checks cache keys for
`/api/tags?workspaceId=${workspaceId}`) remove the redundant check and instead,
after ensuring key includes "search=", return only key.includes("search=&");
keep the surrounding checks for typeof key and
startsWith(`/api/tags?workspaceId=${workspaceId}`) and leave the updater that
prepends newTag unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a8dd980a-7e9f-47f3-8b80-e29dfe407818

📥 Commits

Reviewing files that changed from the base of the PR and between 4e7e141 and 4e31f41.

📒 Files selected for processing (1)
  • apps/web/ui/links/link-builder/tag-select.tsx

@devkiran devkiran requested a review from pepeladeira April 7, 2026 16:23
@steven-tey
Copy link
Copy Markdown
Collaborator

@MaanLad thank you so much for the PR! I can't seem to reproduce the error anymore – it might've been fixed via #1813

Can you confirm that the bug is fixed on main as well?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Client-side error when re-selecting a newly created tag

3 participants