Skip to content

statusText missing in Error Boundary props when using throw data() #14533

@philipchristopher

Description

@philipchristopher

Reproduction

Go to: https://stackblitz.com/edit/github-6va9v5ec?file=app%2Froot.tsx

I've thrown a data() error (with a status text) in the loader of root.tsx. The response is logged in the <ErrorBoundary/>.

View your terminal to see the statusText log an empty string:

Error:  ErrorResponseImpl {
  status: 403,
  statusText: '',
  internal: false,
  data: 'Not Found'
}
❌ error.statusText:  

System Info

System:
    OS: macOS 15.7.1
    CPU: (11) arm64 Apple M3 Pro
    Memory: 1.72 GB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.19.0 - /Users/philip/.nvm/versions/node/v20.19.0/bin/node
    Yarn: 1.22.22 - /Users/philip/.nvm/versions/node/v20.14.0/bin/yarn
    npm: 10.8.2 - /Users/philip/.nvm/versions/node/v20.19.0/bin/npm
    pnpm: 10.17.0 - /Users/philip/.nvm/versions/node/v20.14.0/bin/pnpm
  Browsers:
    Chrome: 142.0.7444.162
    Firefox: 141.0
    Safari: 26.0.1
  npmPackages:
    @react-router/dev: ^7.9.2 => 7.9.5 
    @react-router/node: ^7.9.2 => 7.9.5 
    @react-router/serve: ^7.9.2 => 7.9.5 
    react-router: ^7.9.2 => 7.9.5 
    vite: ^7.1.7 => 7.2.2

Used Package Manager

npm

Expected Behavior

When throwing an error with a status code and status text using data(), I expect the error prop from <ErrorBoundary/> to have it's statusText populated.

Eg:

export const loader = async () => {
  throw data("Not Found", {
    status: 403,
    statusText: "Here is my custom error message!",
  });
};

export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
  if (isRouteErrorResponse(error)) {
    console.log("Error: ", error);
    console.log("❌ error.statusText: ", error.statusText);
  }
};

// Terminal logs

Error:  ErrorResponseImpl {
  status: 403,
  statusText: 'Here is my custom error message!',
  internal: false,
  data: 'Not Found'
}
❌ error.statusText: 'Here is my custom error message!'  

Actual Behavior

However the statusText is empty when logging the error prop in the <ErrorBoundary/>:

export const loader = async () => {
  throw data("Not Found", {
    status: 403,
    statusText: "Here is my custom error message!",
  });
};

export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
  if (isRouteErrorResponse(error)) {
    console.log("Error: ", error);
    console.log("❌ error.statusText: ", error.statusText);
  }
};

// Terminal logs

Error:  ErrorResponseImpl {
  status: 403,
  statusText: '',
  internal: false,
  data: 'Not Found'
}
❌ error.statusText: ''  

Note

Throwing a new Response() will log the status text correctly, example:

  /**
   * 1. Using `throw new Response` results in the status text being applied correctly.
   */
  throw new Response("Not Found", {
     status: 403,
     statusText: "Here is my custom error message!",
  });

// Terminal logs

Error:  ErrorResponseImpl {
  status: 403,
  statusText: 'Here is my custom error message!',
  internal: false,
  data: 'Not Found'
}
✅ error.statusText: 'Here is my custom error message!'  

The error prop is typed as an ErrorResponse which contains the statusText, which makes me believe there's a bug in the data() as it should be passing the statusText but it is not:

type ErrorResponse = {
    status: number;
    statusText: string;
    data: any;
};

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