# HP9010: The route redirected somewhere else

> HP9010 (unexpected-redirect) means a route ended on a different URL than requested. For signed-in scenarios that land on a login page, the login did not work.

Source: https://hydration.jscrate.dev/docs/issues/hp9010
Last updated: 2026-09-18

HP9010 (`unexpected-redirect`) means the route ended on a different URL than
the one requested, or than its `expectRedirect`. The page that was tested is
the one it landed on. When a signed-in scenario lands on the login page, its
login did not work. Otherwise, set `expectRedirect` or limit the route to the
scenarios that can open it.

| | |
| --- | --- |
| Code | `HP9010` |
| Name | `unexpected-redirect` |
| Default severity | Warning |
| Group | Test run problems |
| What it means | The route ended on a different URL than requested (or than expectRedirect). A signed-in scenario that lands on a login page usually means its login did not work. |

## What the HP9010 unexpected redirect finding means

hydration-proof compares the path it requested with the path the page ended
on, after every redirect:

```text
/account redirected to /login; the page that was tested is /login.
/old-pricing should redirect to /pricing but ended on /.
```

Without `expectRedirect`, any redirect is a warning. With `expectRedirect`, a
redirect to another path is an error, because the route is known to go
somewhere else.

## Likely causes

- A signed-in page tested in a scenario that is not signed in, or whose sign-in
  did not leave a working session.
- A route that redirects on purpose: an old URL, a locale prefix, a trailing
  slash rule.
- Middleware that redirects the test browser, for example by locale or
  country.

## How to fix it

If the redirect is intended, set `expectRedirect` on the route, or limit the
route to the scenarios that can open it (scenario `include`/`exclude`). For
signed-in scenarios, check the login step or the storage state file.

### A redirect that is intended

```ts title="hydration-proof.config.ts"
import { defineConfig } from "hydration-proof";

export default defineConfig({
  routes: {
    paths: ["/", { path: "/old-pricing", expectRedirect: "/pricing" }],
  },
  scenarios: [
    { name: "guest", exclude: ["/account/**"] },
    {
      name: "customer",
      include: ["/account/**"],
      storageState: "auth/customer.json",
    },
  ],
});
```

### A login that did not work

1. Watch the login with the browser visible and one worker (the command is
   below).
2. Make the `login` function wait for the page after signing in, for example
   with `page.waitForURL("**/account")`, so the session cookie is set before
   the pages are tested.
3. Check that the session cookie is not limited to another domain than the
   tested app.
4. With `storageState`, record the file again: sessions in it expire.

```bash
npx hydration-proof test --scenario customer --headed --workers 1
```

A `login` that throws stops the run with exit code 2; HP9010 means it finished
but left no working session. [Scenarios and sign-in](https://hydration.jscrate.dev/docs/scenarios) has a
full example.

## Related

- [Scenarios and signed-in pages](https://hydration.jscrate.dev/docs/scenarios)
- [Troubleshooting: signed-in pages end on the login page](https://hydration.jscrate.dev/docs/troubleshooting)
- [HP9005: the server answered with an error status](https://hydration.jscrate.dev/docs/issues/hp9005)
- [HP9002: no React found on the page](https://hydration.jscrate.dev/docs/issues/hp9002)
- [Route options such as expectRedirect](https://hydration.jscrate.dev/docs/routes)
