Skip to content

Commit 84698b5

Browse files
authored
fix(ui): surface silent failures in component renderer (#8379)
1 parent f1d257d commit 84698b5

2 files changed

Lines changed: 39 additions & 22 deletions

File tree

.changeset/ui-mount-diagnostic.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clerk/ui": patch
3+
---
4+
5+
Surface initialization errors and stalled mounts in the component renderer. The internal `ensureMounted` pipeline now logs a `[Clerk UI]` error to the console when the lazy module import rejects, and emits a diagnostic warning if the renderer has not mounted within 10 seconds. Makes silent failures (e.g. failed dev-server chunk loads, unresolved lazy-compilation proxies) surface with an actionable message instead of hanging without feedback.

packages/ui/src/Components.tsx

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -236,29 +236,41 @@ export const mountComponentRenderer = (
236236
// .unmountComponent incorrectly called before the component is rendered
237237
if (!componentsControlsResolver) {
238238
const deferredPromise = createDeferredPromise();
239-
componentsControlsResolver = import('./lazyModules/common').then(({ createRoot }) => {
240-
createRoot(clerkRoot).render(
241-
<Components
242-
getClerk={getClerk}
243-
getEnvironment={getEnvironment}
244-
options={options}
245-
onComponentsMounted={() => {
246-
// Defer warning check to avoid blocking component mount
247-
// Only check in development mode (based on publishable key, not NODE_ENV)
248-
if (getClerk().instanceType === 'development') {
249-
const scheduleWarningCheck =
250-
typeof requestIdleCallback === 'function'
251-
? requestIdleCallback
252-
: (cb: () => void) => setTimeout(cb, 0);
253-
scheduleWarningCheck(() => warnAboutCustomizationWithoutPinning(options));
254-
}
255-
deferredPromise.resolve();
256-
}}
257-
moduleManager={moduleManager}
258-
/>,
239+
const mountTimeout = setTimeout(() => {
240+
console.error(
241+
'[Clerk UI] Component renderer did not mount within 10s. Common causes: a failed chunk load, a dev-server misconfiguration (e.g. unresolved lazy-compilation proxy), or a ClerkProvider/mountX call before the page is hydrated. Check the Network tab for stalled or empty requests.',
259242
);
260-
return deferredPromise.promise.then(() => componentsControls);
261-
});
243+
}, 10_000);
244+
componentsControlsResolver = import('./lazyModules/common')
245+
.then(({ createRoot }) => {
246+
createRoot(clerkRoot).render(
247+
<Components
248+
getClerk={getClerk}
249+
getEnvironment={getEnvironment}
250+
options={options}
251+
onComponentsMounted={() => {
252+
clearTimeout(mountTimeout);
253+
// Defer warning check to avoid blocking component mount
254+
// Only check in development mode (based on publishable key, not NODE_ENV)
255+
if (getClerk().instanceType === 'development') {
256+
const scheduleWarningCheck =
257+
typeof requestIdleCallback === 'function'
258+
? requestIdleCallback
259+
: (cb: () => void) => setTimeout(cb, 0);
260+
scheduleWarningCheck(() => warnAboutCustomizationWithoutPinning(options));
261+
}
262+
deferredPromise.resolve();
263+
}}
264+
moduleManager={moduleManager}
265+
/>,
266+
);
267+
return deferredPromise.promise.then(() => componentsControls);
268+
})
269+
.catch(err => {
270+
clearTimeout(mountTimeout);
271+
console.error('[Clerk UI] Failed to initialize component renderer:', err);
272+
throw err;
273+
});
262274
}
263275
return componentsControlsResolver.then(controls => controls);
264276
},

0 commit comments

Comments
 (0)