Skip to content

Redirecting from server hook (with remote command) fails #14858

Description

@Tinggaard

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions