Skip to content

fix(dashboard): bypass Rive in folder create/subfolder dialogs#1888

Merged
richiemcilroy merged 1 commit into
CapSoftware:mainfrom
alexis-morain:fix/rive-folder-dialog-crash
Jun 13, 2026
Merged

fix(dashboard): bypass Rive in folder create/subfolder dialogs#1888
richiemcilroy merged 1 commit into
CapSoftware:mainfrom
alexis-morain:fix/rive-folder-dialog-crash

Conversation

@alexis-morain

@alexis-morain alexis-morain commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

NewFolderDialog and SubfolderDialog render four sibling Rive components (NormalFolder / BlueFolder / RedFolder / YellowFolder), each calling useRive with the same riveFile returned by a parent useRiveFile. On Next 16 + React 19 + @rive-app/react-canvas@^4.18.7 this triggers a race between the four useRive inits when the dialog mounts — the runtime ends up reading isPlaying / stateMachines on an undefined Rive instance, throws inside setupRiveListeners, and the React reconciler bounces between two chunks in an infinite up/ud recursion that takes down the whole page.

Repro

  1. Self-host or run main with React 19 / Next 16.
  2. Dashboard → caps → click New Folder.
  3. Page crashes; console shows:
    Uncaught TypeError: Cannot read properties of undefined (reading 'isPlaying')
    TypeError: Cannot read properties of undefined (reading 'stateMachines')
        at t.setupRiveListeners
    
    followed by an infinite iv → up → ud → up → ud … stack.

Fix

Replace the four sibling Rive components in the two creation dialogs with a single FontAwesomeIcon (faFolder) tinted per colour choice. The dialog still shows four labelled, selectable swatches; only the hover open/close animation is dropped.

Folder cards on the dashboard (Folder.tsx) keep their Rive runtime because each card owns its own useRive call and never shares a riveFile — that path doesn't hit the race.

Test plan

  • Open New Folder → dialog renders, four colour swatches visible.
  • Pick a colour → swatch highlights, Create button enables when a name is typed.
  • Folder created, dashboard refreshes.
  • Same flow from inside a folder via New Subfolder.
  • Existing folder cards on the dashboard still animate on hover (Rive unaffected).

Notes

This is a workaround targeting the race, not an upstream Rive fix. A proper fix probably belongs in @rive-app/react-canvas (init sequencing when a shared riveFile is consumed by multiple useRive hooks). Happy to revert if a newer rive-react release resolves it.

Greptile Summary

This PR fixes a crash in the New Folder and New Subfolder dialogs caused by a race condition when four sibling Rive components each called useRive with the same shared riveFile instance under React 19 / Next 16, ultimately triggering an infinite reconciler loop. The fix replaces the animated Rive swatches with static FontAwesomeIcon (faFolder) icons tinted per colour option, preserving all functional behaviour (colour selection, create mutation, form reset) while sidestepping the upstream @rive-app/react-canvas race entirely.

  • NewFolderDialog.tsx and SubfolderDialog.tsx: useRiveFile, the four Rive sub-components, folderRefs, and onMouseEnter/onMouseLeave handlers are removed; FolderOptions gains a color hex string and renders a FontAwesomeIcon in their place.
  • The Rive runtime is untouched on the dashboard folder cards (Folder.tsx), which each own an independent useRive call and do not share a riveFile.

Confidence Score: 5/5

Straightforward removal of a crashing code path; all functional dialog behaviour is preserved.

The change is a targeted deletion of the Rive initialisation code in two symmetrical dialog components. The colour-selection state machine, create mutation, and dialog reset logic are unmodified. No new dependencies are introduced, and the FontAwesomeIcon rendering path has no side-effects that could introduce regressions.

No files require special attention.

Important Files Changed

Filename Overview
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx Replaces four sibling Rive components with a single FontAwesomeIcon per swatch, removing the shared-riveFile race; logic for color selection, create mutation, and public toggle is unchanged.
apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx Identical treatment to NewFolderDialog — Rive removed, FontAwesomeIcon substituted; subfolder creation mutation and reset logic intact.

Reviews (2): Last reviewed commit: "fix(dashboard): bypass Rive in folder cr..." | Re-trigger Greptile

@alexis-morain alexis-morain force-pushed the fix/rive-folder-dialog-crash branch from cb149c9 to 75e6581 Compare June 10, 2026 11:14
@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

The New Folder and New Subfolder dialogs share a single riveFile (from
useRiveFile) across four sibling color components. With React 19 concurrent
rendering this triggers a race in @rive-app/react-canvas during state-machine
init, crashing the dialog with an infinite up/ud recursion
("Cannot read properties of undefined (reading 'isPlaying'/'stateMachines')").

Replace the Rive folder icons with colored FontAwesome faFolder icons in both
dialogs. The public collection field and folder creation logic are untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alexis-morain alexis-morain force-pushed the fix/rive-folder-dialog-crash branch from 75e6581 to 42113be Compare June 10, 2026 11:30
@alexis-morain

Copy link
Copy Markdown
Contributor Author

Friendly nudge on this one, @richiemcilroy. It's a self-host crash fix (folder create/subfolder dialogs hard-crash the page on React 19 / Next 16 due to four sibling useRive hooks sharing one riveFile). I've rebased it on main after #1906, so it no longer conflicts with the collections work that touched these dialogs. The two Greptile P2 nits (redundant icon color prop) are already resolved in the current head. CI is green (only the Vercel deploy check fails, which needs maintainer authorization). Happy to adjust the approach if you'd prefer fixing the init sequencing upstream in rive-react instead.

@richiemcilroy

Copy link
Copy Markdown
Member

hey @greptileai please review the PR

@richiemcilroy

Copy link
Copy Markdown
Member

Thanks for this @alexis-morain - taking a look!

@richiemcilroy richiemcilroy merged commit 0eb6d2f into CapSoftware:main Jun 13, 2026
15 of 16 checks passed
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.

2 participants