Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/ui-mount-diagnostic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/ui": patch
---

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.
56 changes: 34 additions & 22 deletions packages/ui/src/Components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,29 +236,41 @@ export const mountComponentRenderer = (
// .unmountComponent incorrectly called before the component is rendered
if (!componentsControlsResolver) {
const deferredPromise = createDeferredPromise();
componentsControlsResolver = import('./lazyModules/common').then(({ createRoot }) => {
createRoot(clerkRoot).render(
<Components
getClerk={getClerk}
getEnvironment={getEnvironment}
options={options}
onComponentsMounted={() => {
// Defer warning check to avoid blocking component mount
// Only check in development mode (based on publishable key, not NODE_ENV)
if (getClerk().instanceType === 'development') {
const scheduleWarningCheck =
typeof requestIdleCallback === 'function'
? requestIdleCallback
: (cb: () => void) => setTimeout(cb, 0);
scheduleWarningCheck(() => warnAboutCustomizationWithoutPinning(options));
}
deferredPromise.resolve();
}}
moduleManager={moduleManager}
/>,
const mountTimeout = setTimeout(() => {
console.error(
'[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.',
);
return deferredPromise.promise.then(() => componentsControls);
});
}, 10_000);
componentsControlsResolver = import('./lazyModules/common')
.then(({ createRoot }) => {
createRoot(clerkRoot).render(
<Components
getClerk={getClerk}
getEnvironment={getEnvironment}
options={options}
onComponentsMounted={() => {
clearTimeout(mountTimeout);
// Defer warning check to avoid blocking component mount
// Only check in development mode (based on publishable key, not NODE_ENV)
if (getClerk().instanceType === 'development') {
const scheduleWarningCheck =
typeof requestIdleCallback === 'function'
? requestIdleCallback
: (cb: () => void) => setTimeout(cb, 0);
scheduleWarningCheck(() => warnAboutCustomizationWithoutPinning(options));
}
deferredPromise.resolve();
}}
moduleManager={moduleManager}
/>,
);
return deferredPromise.promise.then(() => componentsControls);
})
.catch(err => {
clearTimeout(mountTimeout);
console.error('[Clerk UI] Failed to initialize component renderer:', err);
throw err;
});
}
return componentsControlsResolver.then(controls => controls);
},
Expand Down
Loading