sveltejs / sveltejs/kit

Redirecting from server hook (with remote command) fails

Open
#14,858 6 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
20.8k
Forks
2.3k
Avg merge
1d 16h
Merged PRs (30d)
156

Description

Describe the bug

If the hooks.server.ts redirects during the handle of a remote command, neither the redirect nor the body of the command gets executed, instead an error is shown that redirects cannot happen in remote commands.

I have setup in which the server hook will redirect if the users refresh token expires, which sometimes happens in between navigation, when the user presses a button to trigger a remote command.

It is of course possible to overcome this issue, by using a query function instead, but it is not ideal (or to me at least not described properly in the docs), that the limitations disallowing redirects in a command, also propagate to the server hook.

Essentially, having this auth-expiry kind of redirect in the server hook disallows any usage of remote command functions. Is it possible to overcome this somehow? Otherwise I would suggest to have the docs state this more clearly - that the disallowed redirects also account for the hook, not just the body of the remote command.

Reproduction

https://stackblitz.com/github/Tinggaard/remote-command-redirect-hook

In short terms:

src/hooks.server.ts

import { redirect, type Handle } from "@sveltejs/kit";

export const handle: Handle = async ({ event, resolve }) => {
  // some logic here that redirects if the users auth token is about to expire or the like
  // could happen when a remote request is invoked - hardcoded for the purpose of the demo
  if (event.isRemoteRequest)
    redirect(307, '/auth')

  return await resolve(event);
};

src/routes/cmd.remote.ts

import { command } from "$app/server";
import z from "zod";

export const foo = command(z.string(), (_) => {
  console.log('Command invoked!');
});

src/routes/+page.svelte

<script lang="ts">
  import { foo } from "./cmd.remote";
</script>

<svelte:boundary>
  <button onclick={async () => await foo("bar")}>trigger!</button>

  {#snippet pending()}
    loading...
  {/snippet}

  {#snippet failed(error, reset)}
    <pre>{error}</pre>

    <button onclick={reset}>Try again</button>
  {/snippet}
</svelte:boundary>

Invoking the remote command neither redirects nor executes the function body.

Logs

In the client console:

Uncaught (in promise) Error: Redirects are not allowed in commands. Return a result instead and use goto on the client
System Info
System:
    OS: Linux 6.17 Arch Linux
    CPU: (16) x64 AMD Ryzen 7 8845HS w/ Radeon 780M Graphics
    Memory: 21.57 GB / 27.15 GB
    Container: Yes
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 24.9.0 - /usr/bin/node
    npm: 11.6.1 - /usr/bin/npm
    pnpm: 10.18.0 - /usr/bin/pnpm
  Browsers:
    Brave Browser: 139.1.81.137
    Chromium: 141.0.7390.54
    Firefox: 143.0.4
    Firefox Developer Edition: 143.0.4
  npmPackages:
    @sveltejs/adapter-auto: ^6.1.0 => 6.1.1
    @sveltejs/kit: ^2.43.2 => 2.48.3
    @sveltejs/vite-plugin-svelte: ^6.2.0 => 6.2.1
    svelte: ^5.39.5 => 5.43.0
    vite: ^7.1.7 => 7.1.12
Severity

serious, but I can work around it

Additional Information

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/hooks.server.ts and src/routes/cmd.remote.ts, then reproduce the behavior from the linked StackBlitz example using the remote command and server hook redirect. Trace how the redirect reaches the client and compare it with the documented command restriction; done means the intended redirect behavior works, or the hook limitation is clearly documented and covered by an appropriate test.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.