From 4ae003a540624d53a752160c3bd36dcc328d3391 Mon Sep 17 00:00:00 2001 From: karilint Date: Fri, 29 May 2026 11:35:54 +0300 Subject: [PATCH 1/2] fix: Fix invalid blocker state transition in UnsavedChangesProvider Fix #1184: Time Unit error caused by invalid blocker state transition. The error 'Invalid blocker state transition: unblocked -> proceeding' occurred when calling blocker.proceed() in UnsavedChangesProvider. Root cause: setDirty(false) was called before blocker.proceed?.(), which triggered a re-render that could change the blocker state before proceed was called. This caused React Router's internal state machine to receive a proceed call when the blocker was no longer in the 'blocked' state. Fix: - Call blocker.proceed?.() before setDirty(false) in handleConfirm - Add additional state check in isSamePathNavigation useEffect to ensure blocker is still 'blocked' before calling proceed() Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- frontend/src/components/UnsavedChangesProvider.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/UnsavedChangesProvider.tsx b/frontend/src/components/UnsavedChangesProvider.tsx index 3ac1f993..9c752055 100644 --- a/frontend/src/components/UnsavedChangesProvider.tsx +++ b/frontend/src/components/UnsavedChangesProvider.tsx @@ -72,8 +72,8 @@ export const UnsavedChangesProvider = ({ const handleConfirm = useCallback(() => { if (blocker.state === 'blocked') { - setDirty(false) blocker.proceed?.() + setDirty(false) } }, [blocker, setDirty]) @@ -91,7 +91,7 @@ export const UnsavedChangesProvider = ({ useEffect(() => { const proceed = blocker.proceed as (() => void) | undefined - if (isSamePathNavigation && proceed) { + if (isSamePathNavigation && proceed && blocker.state === 'blocked') { proceed() } }, [blocker, isSamePathNavigation]) From 7e732d9faae2740897bc329d08cfab9668f67133 Mon Sep 17 00:00:00 2001 From: karilint Date: Fri, 29 May 2026 14:55:42 +0300 Subject: [PATCH 2/2] Remove redundant blocker state guard --- frontend/src/components/UnsavedChangesProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/UnsavedChangesProvider.tsx b/frontend/src/components/UnsavedChangesProvider.tsx index 9c752055..6d6c58cb 100644 --- a/frontend/src/components/UnsavedChangesProvider.tsx +++ b/frontend/src/components/UnsavedChangesProvider.tsx @@ -91,7 +91,7 @@ export const UnsavedChangesProvider = ({ useEffect(() => { const proceed = blocker.proceed as (() => void) | undefined - if (isSamePathNavigation && proceed && blocker.state === 'blocked') { + if (isSamePathNavigation && proceed) { proceed() } }, [blocker, isSamePathNavigation])