---
title: "Manual Setup"
description: "Learn how to set up the SDK manually."
url: https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/
---

# Manual Setup | Sentry for Remix

If you can't (or prefer not to) run the [automatic setup](https://docs.sentry.io/platforms/javascript/guides/remix.md#install), you can follow the instructions below to configure your application.

## [Features](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#features)

In addition to capturing errors, you can monitor interactions between multiple services or applications by [enabling tracing](https://docs.sentry.io/concepts/key-terms/tracing.md). You can also analyze performance profiles from real users with [profiling](https://docs.sentry.io/product/explore/profiling.md). Lastly, adding [session replay](https://docs.sentry.io/product/explore/session-replay/web/getting-started.md) lets you get to the root of an error or performance issue faster by watching a video-like reproduction of a user session.

Select which Sentry features you'd like to install in addition to Error Monitoring to get the corresponding installation and configuration instructions below.

## [Install](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#install)

Error Monitoring\[ ]Tracing\[ ]Profiling\[ ]Session Replay

Get started by installing the Sentry Remix SDK:

```bash
npm install @sentry/remix --save
```

## [Configure](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#configure)

To use this SDK, initialize Sentry in your Remix project for both the client and server.

### [Client-side Configuration](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#client-side-configuration)

`entry.client.tsx`

```typescript
import { useLocation, useMatches } from "@remix-run/react";
import * as Sentry from "@sentry/remix";
import { useEffect } from "react";

Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    // ___PRODUCT_OPTION_START___ performance
    Sentry.browserTracingIntegration({
      useEffect,
      useLocation,
      useMatches,
    }),
    // ___PRODUCT_OPTION_END___ performance
    // ___PRODUCT_OPTION_START___ session-replay
    // Replay is only available in the client
    Sentry.replayIntegration(),
    // ___PRODUCT_OPTION_END___ session-replay
  ],

  // ___PRODUCT_OPTION_START___ performance
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  // We recommend adjusting this value in production
  // Learn more at
  // https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
  tracesSampleRate: 1.0,

  // Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled
  tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
  // ___PRODUCT_OPTION_END___ performance

  // ___PRODUCT_OPTION_START___ session-replay
  // Capture Replay for 10% of all sessions,
  // plus for 100% of sessions with an error
  // Learn more at
  // https://docs.sentry.io/platforms/javascript/session-replay/configuration/#general-integration-configuration
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  // ___PRODUCT_OPTION_END___ session-replay
});
```

#### [Remix ErrorBoundary](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#remix-errorboundary)

To capture errors from [ErrorBoundary](https://remix.run/docs/en/main/route/error-boundary), you should define your own `ErrorBoundary` in `root.tsx` and use `Sentry.captureRemixErrorBoundaryError` inside of it. You can also create route-specific error capturing behavior by defining `ErrorBoundary` in your route components. The `ErrorBoundary` you define in `root.tsx` will be used as a fallback for all routes.

`root.tsx`

```typescript
import { captureRemixErrorBoundaryError } from "@sentry/remix";

export const ErrorBoundary: V2_ErrorBoundaryComponent = () => {
  const error = useRouteError();

  captureRemixErrorBoundaryError(error);

  return <div> ... </div>;
};
```

To catch React component errors (in Remix v1) and routing transactions (in all Remix versions), wrap your Remix root with `withSentry`.

If you use Remix v1 with the `v2_errorBoundary` future flag, you must also configure your `ErrorBoundary`.

`root.tsx`

```typescript
import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

import { withSentry } from "@sentry/remix";

function App() {
  return (
    <html>
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

export default withSentry(App);
```

If you use Remix v2, `wrapWithErrorBoundary` is disabled by default. You still need to wrap your root component with `withSentry` to capture routing transactions.

You can disable or configure `ErrorBoundary` using a second parameter to `withSentry`.

```typescript
withSentry(App, {
  wrapWithErrorBoundary: false,
});

// or

withSentry(App, {
  errorBoundaryOptions: {
    fallback: <p>An error has occurred</p>,
  },
});
```

### [Server-side Configuration](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#server-side-configuration)

Create an instrumentation file (named here as `instrument.server.mjs`) in your project. Add your initialization code in this file for the server-side SDK.

`instrument.server.mjs`

```typescript
import * as Sentry from "@sentry/remix";

Sentry.init({
  dsn: "___PUBLIC_DSN___",
  // ___PRODUCT_OPTION_START___ performance
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  // We recommend adjusting this value in production
  // Learn more at
  // https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
  tracesSampleRate: 1.0,
  // ___PRODUCT_OPTION_END___ performance

  // To use Sentry OpenTelemetry auto-instrumentation
  // default: false
  autoInstrumentRemix: true,

  // Optionally capture action formData attributes with errors.
  // This requires `sendDefaultPii` set to true as well.
  captureActionFormDataKeys: {
    key_x: true,
    key_y: true,
  },
  // To capture action formData attributes.
  sendDefaultPii: true,
});
```

Then run your Remix server with:

```bash
NODE_OPTIONS='--import=./instrument.server.mjs' remix-serve build
# or
NODE_OPTIONS='--require=./instrument.server.cjs' remix-serve build
```

If you use the Express server instead of the Remix built-in server, you can alternatively import your instrumentation file directly at the top of your server implementation. See the example [here](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#custom-express-server).

Sentry's Remix SDK will automatically record your [`action`](https://remix.run/docs/en/main/route/action) and [`loader`](https://remix.run/docs/en/main/route/loader) transactions, as well as server-side errors. You can also initialize Sentry's database integrations, such as [Prisma](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/prisma.md), to get spans for your database calls.

#### [Server-Side Errors](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#server-side-errors)

To capture server-side errors automatically, instrument the [`handleError`](https://remix.run/docs/en/main/file-conventions/entry.server#handleerror) function in your server entry point.

If you're using Sentry Remix SDK version `7.87.0` or higher, you can wrap your error handler with `wrapHandleErrorWithSentry` or use `sentryHandleError` to export as your `handleError` function.

`entry.server.tsx (@sentry/remix >= 7.87.0)`

```typescript
import * as Sentry from "@sentry/remix";

export const handleError = Sentry.wrapHandleErrorWithSentry(
  (error, { request }) => {
    // Custom handleError implementation
  },
);

// Alternative: Use the Sentry utility function if you don't need to wrap a custom function
export const handleError = Sentry.sentryHandleError;
```

For SDK versions older than `7.87.0`, you can use `Sentry.captureRemixServerException` to capture errors inside `handleError`.

`entry.server.tsx (@sentry/remix < 7.87.0)`

```typescript
export function handleError(
  error: unknown,
  { request }: DataFunctionArgs,
): void {
  if (error instanceof Error) {
    Sentry.captureRemixServerException(error, "remix.server", request);
  } else {
    // Optionally capture non-Error objects
    Sentry.captureException(error);
  }
}
```

### [Source Maps Upload](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#source-maps-upload)

To enable readable stack traces, [configure source maps upload](https://docs.sentry.io/platforms/javascript/guides/remix/sourcemaps.md) for your production builds.

After you've completed this setup, the SDK will automatically capture unhandled errors and promise rejections, and monitor performance. You can also [manually capture errors](https://docs.sentry.io/platforms/javascript/guides/remix/usage.md).

## [Verify](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#verify)

This snippet includes an intentional error, so you can test that everything is working as soon as you set it up.

Errors triggered from within Browser DevTools are sandboxed, so will not trigger an error handler. Place the snippet directly in your code instead.

Then, throw an error in a `loader` or `action`.

`routes/error.tsx`

```typescript
export const action: ActionFunction = async ({ request }) => {
  throw new Error("Sentry Error");
};
```

Learn more about manually capturing an error or message in our [Usage documentation](https://docs.sentry.io/platforms/javascript/guides/remix/usage.md).

To view and resolve the recorded error, log into [sentry.io](https://sentry.io) and select your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved.

You can refer to [Remix Docs](https://remix.run/docs/en/main/guides/envvars#browser-environment-variables) to learn how to use your Sentry DSN with environment variables.

## [Custom Express Server](https://docs.sentry.io/platforms/javascript/guides/remix/manual-setup__v8.x/#custom-express-server)

You can import your server instrumentation file at the top of your Express server implementation.

`server.ts`

```typescript
// import the Sentry instrumentation file before anything else.
import "./instrument.server.mjs";
// alternatively `require('./instrument.server.cjs')`

// ...

const app = express();

// ...
```
