Skip to content

throwing a Redirect is incorrectly handled as an Error, not a Response. #8617

@aslakhellesoy

Description

@aslakhellesoy

Describe the bug

Calling throw redirect(code, path) throws a Redirect object. (In JavaScript, anything can be thrown, it doesn't have to be an Error)

When SvelteKit catches a thrown object, it tries to deterimne whether the thrown object is a Redirect object (in which case it converts it to a Response). Otherwise it is handled as an error.

SvelteKit uses error instanceof Redirect in a few places to make this check.

This works fine if there is only one implementation of Redirect, but there might actually be more than one. In that case, the instanceof check will return false, treating a redirect as an error.

So why are there more than two implementations of Redirect? I searched for "grotesque" to find out 😄 .

/**
* This is a grotesque hack that, in dev, allows us to replace the implementations
* of these classes that you'd get by importing them from `@sveltejs/kit` with the
* ones that are imported via Vite and loaded internally, so that instanceof
* checks work even though SvelteKit imports this module via Vite and consumers
* import it via Node
* @param {{
* ActionFailure: typeof ActionFailure;
* HttpError: typeof HttpError;
* Redirect: typeof Redirect;
* }} implementations
*/
export function replace_implementations(implementations) {
ActionFailure = implementations.ActionFailure;
HttpError = implementations.HttpError;
Redirect = implementations.Redirect;
}

In other words, replace_implementations causes error instanceof Redirect to always return false.
This is what breaks the redirect behaviour.

I'm not sure how best to fix this. Perhaps by replacing error instanceof Redirect with isRedirect(error):

function isRedirect(object) {
    return 'status' in object && 
           'location' in object && 
           typeof object.status === 'number' && 
           typeof object.location === 'string'
}

If you think this is a good solution I'd be happy to submit a PR.

Reproduction

I'm sorry, I haven't prepared one. But many people seem to have a problem with this on Discord.

Logs

No response

System Info

System:
    OS: macOS 13.0.1
    CPU: (8) x64 Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
    Memory: 1.49 GB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.18.1 - ~/.asdf/installs/nodejs/16.18.1/bin/node
    npm: 8.19.2 - ~/.asdf/plugins/nodejs/shims/npm
  Browsers:
    Chrome: 109.0.5414.87
    Firefox: 108.0.2
    Safari: 16.1
  npmPackages:
    @sveltejs/adapter-cloudflare: 1.0.4 => 1.0.4
    @sveltejs/kit: 1.0.13 => 1.0.13
    svelte: 3.55.1 => 3.55.1
    vite: 4.0.4 => 4.0.4

Severity

blocking all usage of SvelteKit

Additional Information

I've tried @sveltejs/kit versions between 1.0.10 and 1.1.4, and they all seem to have the bug.

Because the bug has only surfaced in the past 24h or so (I think), it is probably triggered by a dependency that has moved underneath. Perhaps vite.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions