router icon indicating copy to clipboard operation
router copied to clipboard

Application stuck in "pending" state when `notFound()` is thrown from a $param route

Open melv-n opened this issue 1 year ago • 1 comments

Describe the bug

If you throw notFound() for a $param param route with a delay (e.g. when awaiting a request), the parent routes stay forever stuck in "pending" state.

This behaviour does not happen if the loader promise resolves very quick, e.g. within 100ms.

Simplest reproduction:

export const Route = createFileRoute('/posts/$postId')({
  loader: async ({ params }) => {
    try {
      // Simulate a slow request. Resolving this within 100ms works fine, but if it takes longer
      // the route state will be forever stuck in pending.
      await new Promise((resolve, reject) => {
        setTimeout(() => {
          reject();
        }, 1000);
      });
    } catch (err) {
      // Never shows
      throw notFound();
    }
  },

  notFoundComponent: () => <div>Post not found</div>,
});

Your Example Website or App

https://stackblitz.com/edit/tanstack-router-jc3pyp?file=src%2Froutes%2Findex.tsx

Steps to Reproduce the Bug or Issue

  1. GO to /posts/whatever in Stackblitz (posts.$postId.tsx)
  2. OR: Go to the /browse/album/123 URL in StackBlitz

Expected behavior

A "Not found message"

Actual behavior

The matched root route is stuck in a pending state according to the dev tools, the final route correctly has "not found" state.

This causes the page to never load.

Platform

  • OS: macOS
  • Browser: Arc (Chrome)
  • Version: 1.47

Additional context

No response

melv-n avatar Jun 20 '24 15:06 melv-n

@tannerlinsley This is currently very broken, where the router gets forever stuck in a pending state when throw notFound() in any async loader or beforeLoad. Latest TSR version (v1.40.0)

Simplest repro (updated Stackblitz):

export const Route = createFileRoute('/posts/$postId')({
  loader: async ({ params }) => {
    try {
      // Simulate a slow request. Resolving this within 100ms works fine, but if it takes longer
      // the route state will be forever stuck in pending.
      await new Promise((resolve, reject) => {
        setTimeout(() => {
          reject();
        }, 1000);
      });
    } catch (err) {
      // Never shows
      throw notFound();
    }
  },

  // Expectation: See this component after 1000ms
  notFoundComponent: () => <div>Post not found</div>,
});

melv-n avatar Jun 27 '24 16:06 melv-n

@schiller-manuel Would be amazing if you could confirm this use-case is also solved by #1907 😍

melv-n avatar Jul 07 '24 14:07 melv-n

not solved (yet) unfortunately

schiller-manuel avatar Jul 07 '24 14:07 schiller-manuel

This will be fixed in 752a136140de515c5cf48d3da5cb88cc44d3c97c

tannerlinsley avatar Jul 08 '24 14:07 tannerlinsley

reproducer with pre-release package: https://stackblitz.com/edit/tanstack-router-t7vccx?file=src%2Froutes%2Fposts.%24postId.tsx

schiller-manuel avatar Jul 08 '24 17:07 schiller-manuel

I still have the same issue now

myeljoud avatar May 29 '25 04:05 myeljoud

@myeljoud please create a new GitHub issue including a complete minimal example

schiller-manuel avatar May 29 '25 08:05 schiller-manuel