Skip to content

docs: clarify that shared getRequestEvent() auth helpers need isRedirect() handling for command() #16275

Description

@hyunbinseo

Describe the problem

getRequestEvent() makes it possible to write shared, reusable auth helpers like this: #13582

import { redirect } from '@sveltejs/kit';
import { getRequestEvent } from '$app/server';

export function requireLogin() {
  const { locals, url } = getRequestEvent();

  // assume `locals.user` is populated in `handle`
  if (!locals.user) {
    const location = new URL('/login', url.origin);
    location.searchParams.set('redirectTo', url.pathname);

    redirect(307, location);
  }

  return locals.user;
}

However, redirect() is explicitly disallowed inside command(). If requireLogin() (or any shared helper that redirects) is called from inside a command, the redirect gets caught server-side, serialized, and then the client throws:

Error: Redirects are not allowed in commands. Return a result instead and use goto on the client

Describe the proposed solution

The remote functions docs should show how to safely reuse a redirect()-based helper inside a command()

// server: saveSession.remote.ts
} catch (e) {
  if (isRedirect(e)) return { error: 'UNAUTHENTICATED' as const, location: e.location };
  throw e;
}
// client
const response = await myCommand(data);
if (response.error === 'UNAUTHENTICATED') goto(response.location);

Alternatives considered

SvelteKit could change the client command() runtime to throw something callers can actually inspect, rather than a message-only Error. Then isRedirect() (already a public, universal export) would work in the catch block exactly the way one would intuitively expect:

// client
import { isRedirect } from '@sveltejs/kit';
import { goto } from '$app/navigation';

try {
  const response = await myCommand(data);
} catch (e) {
  if (isRedirect(e)) {
    goto(e.location);
    return;
  }
  throw e;
}

Importance

would make my life easier

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions