solid-router icon indicating copy to clipboard operation
solid-router copied to clipboard

Crash when server function throws redirect and wrapped in createAsync

Open apatrida opened this issue 1 year ago • 4 comments

Describe the bug

If you throw a redirect from a server function wrapped in createAsync it does not handle the redirect nor serialize it across. Server functions called as actions might want to throw redirects, and if used elsewhere it is likely they would as well. cache wrapping handles the redirect, but if you do not want caching, you do not have a noCache option and therefore throw or return a redirect causing what? currently a crash.

Example:

async function serverApiCallThrow(isIndirect?: boolean): Promise<string> {
    'use server';
    throw redirect(`/${isIndirect ? 'fromIndirect' : 'fromThrow'}/whateva?q=456`);
    return 'ok'
}

...
  const asyncThing = createAsync(()=>serverApiCallThrow())
  
...
  <Show when={asyncThing()}>
      <div>boo!</div>
  </Show>

results in exception:

Error: Unknown error at castError (...server bundle...)

and client shows:

Screenshot 2024-05-26 at 8 26 41 AM

Your Example Website or App

see above

Steps to Reproduce the Bug or Issue

  1. create a server function
  2. throw a redirect in that functino
  3. use in a component with createAsync
  4. boom

Expected behavior

The redirect happens or thrown as error, but not a serialization crash

Screenshots or Videos

No response

Platform

any

Additional context

No response

apatrida avatar May 26 '24 14:05 apatrida

From what I can tell this is already being thrown as a normal error and not a crash - wrapping the <Show> in an ErrorBoundary functions as you'd expect. Perhaps just a better error message is necessary?

Brendonovich avatar Jun 07 '24 09:06 Brendonovich

I think the issue here is that instead of handling the redirect, and navigating user to the new url, it throws an error. I don't think wrapping <Show> in ErrorBoundary will help.

From the docs it seems that only cache and action functions know how to correctly handle redirects. But I think there are cases, when we don't want to cache this function. For me it seems like missing functionality. We can try to use some workarounds, like cache revalidation, or pass some dummy random argument, so it will always produce unique cache key, but that doesn't seem as right thing to do.

maksimsemenov avatar Jun 13 '24 14:06 maksimsemenov

Yeah cache and action are the only wrappers that handle redirects, it's possible that a third neutral one is needed. Even then a thrown response in a raw server function surfacing as an error is still expected behaviour, it could just be reported better. Wrapping the <Show> in ErrorBoundary doesn't help, but it functions as you'd expect any other error to (repo) rather than causing a crash which would be more worrying.

Brendonovich avatar Jun 13 '24 15:06 Brendonovich

Just flagging here that I stumbled upon this problem as well. It'd be useful to have another more neutral way of sending redirects.

I was fetching some session data from the server and if it's not present I wanted to redirect to the sign in page. I ended up wrapping the function in an action but had to go through all the useAction / useSubmission overhead to be able to get the value. createAsync already returned a signal which is easier to handle.

sfnmk avatar Feb 04 '25 00:02 sfnmk