Sentry Raven Middleware for Redux
raw JSON →raven-for-redux is a Redux middleware designed to integrate Redux state and actions with Sentry's error tracking platform through the legacy raven-js client. It intercepts dispatched actions, logging their types as breadcrumbs and attaching the last action and current Redux state as additional context to all errors, not just reducer exceptions. As of version 1.4.0, it requires raven-js version 3.9.0 or higher, with a known bug triggered by raven-js 3.14.0. The library differentiates itself by allowing the Sentry Raven client to be injected, providing flexible configuration, and offering options to filter action breadcrumbs and define user context mappings from the Redux state. Its release cadence has been infrequent, and its primary dependency, raven-js, is officially deprecated in favor of `@sentry/browser`, making this package suitable only for projects using older Sentry integrations.
Common errors
error TypeError: Cannot read properties of undefined (reading 'config') at createRavenMiddleware ↓
Raven.config('<YOUR_DSN>').install(); is called and completes successfully before creating the middleware, and that the initialized Raven object is passed as the first argument to createRavenMiddleware. error Sentry: Breadcrumbs or errors are not being reported, or are malformed in Sentry dashboard. ↓
raven-js dependency to a version other than 3.14.0, or preferably, migrate your Sentry integration to the actively maintained @sentry/browser package. error Actions appear in Sentry breadcrumbs without expected modifications from other middlewares, or the attached state context is incorrect/stale. ↓
createRavenMiddleware is placed after any other middlewares that modify actions or state (e.g., redux-thunk, redux-promise, redux-saga). Warnings
breaking The underlying Sentry client, `raven-js`, is officially deprecated by Sentry. New projects should migrate to `@sentry/browser` and `@sentry/redux` for modern Sentry integration. ↓
gotcha A specific bug exists in `raven-js` version 3.14.0 that can be triggered by `raven-for-redux`, potentially preventing breadcrumbs or errors from being reported correctly. ↓
gotcha `raven-for-redux` middleware should be placed *after* other Redux middlewares (like `redux-thunk` or `redux-promise`) that might intercept, transform, or emit new actions. Incorrect placement can lead to actions not being logged or incorrect state being attached. ↓
gotcha The `breadcrumbDataFromAction` option, while powerful, should be used with caution. Logging large or sensitive portions of the action object or state can negatively impact performance and Sentry event size limits. ↓
gotcha When using TypeScript with `raven-for-redux`'s DefinitelyTyped bindings, the import style for `createRavenMiddleware` differs from typical ES module default imports. ↓
Install
npm install raven-for-redux yarn add raven-for-redux pnpm add raven-for-redux Imports
- createRavenMiddleware wrong
import { createRavenMiddleware } from 'raven-for-redux';correctimport createRavenMiddleware from 'raven-for-redux'; - createRavenMiddleware (TypeScript) wrong
import createRavenMiddleware from 'raven-for-redux';correctimport * as createRavenMiddleware from 'raven-for-redux'; - Raven wrong
const Raven = require('raven-js');correctimport Raven from 'raven-js';
Quickstart
import Raven from "raven-js";
import { createStore, applyMiddleware, combineReducers } from "redux";
import createRavenMiddleware from "raven-for-redux";
// Mock reducer for demonstration
const initialState = { count: 0, user: { id: 1, name: 'Guest' } };
function reducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
case 'LOGIN':
return { ...state, user: action.payload };
default:
return state;
}
}
// Initialize Raven (or mock it for local development without a DSN)
const SENTRY_DSN = process.env.SENTRY_DSN ?? "https://examplePublicKey@o0.ingest.sentry.io/0";
// In a real application, you would always provide a valid DSN.
Raven.config(SENTRY_DSN).install();
const store = createStore(
reducer,
applyMiddleware(
// Middlewares that intercept or emit actions should generally precede raven-for-redux.
createRavenMiddleware(Raven, {
breadcrumbMessageFromAction: action => action.type,
breadcrumbDataFromAction: action => ({ actionPayload: action.payload }),
stateContext: state => ({ user: state.user }),
actionFilter: action => action.type !== 'IGNORE_THIS_ACTION'
})
)
);
// Dispatch some actions to generate breadcrumbs
store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'LOGIN', payload: { id: 123, name: 'Alice' } });
store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'IGNORE_THIS_ACTION' }); // This action will be filtered out
// Simulate an error to capture state and breadcrumbs
try {
throw new Error("Simulated error during user interaction!");
} catch (e) {
Raven.captureException(e);
}
console.log('Final State:', store.getState());
// In a real app, console.logs would typically be replaced by actual Sentry reports.