diff --git a/webapp/src/router.tsx b/webapp/src/router.tsx index c9ce4130..43a915ec 100644 --- a/webapp/src/router.tsx +++ b/webapp/src/router.tsx @@ -171,6 +171,33 @@ function WorkspaceToTeamRedirect() { return null } +/** + * On initial load only: if URL ends with /error (and not the canonical /error page), redirect to path without it. + * Prevents infinite redirect loop from error boundary's relative URL redirect. + */ +function InitialLoadErrorPathFix() { + const location = useLocation() + const history = useHistory() + const hasRun = React.useRef(false) + + useEffect(() => { + if (hasRun.current) return + hasRun.current = true + + const pathname = location.pathname + if (pathname === '/error' || pathname === '/access-denied') return + if (!pathname.endsWith('/error')) return + + let validPath = pathname + while (validPath.endsWith('/error') && validPath !== '/error') { + validPath = validPath.replace(/\/error$/, '') || '/' + } + history.replace(validPath + location.search) + }, [location.pathname, location.search, history]) + + return null +} + function GlobalErrorRedirect() { const globalError = useAppSelector(getGlobalError) const dispatch = useAppDispatch() @@ -223,6 +250,7 @@ const FocalboardRouter = (props: Props): JSX.Element => { return ( +