"Maximum call stack size exceeded" when using v7 with redux saga
See original GitHub issueHi! I’m not sure what useful information I can provide to help diagnose this issue, but in my app I’ve just recently upgraded to react-redux@7
and started getting the error in the title. I’ve attached a log from the Chrome developer console and expanded the full stack trace. Note that this only seems to be occurring when NODE_ENV === 'production'
. To reiterate: this error does not occur in v6
React: 16.8.6 React-DOM: 16.8.6 Redux: 4.0.1 React-Redux: 7.0.1 Redux-Saga: 1.0.2
Formik: 1.5.2 Firebase: 5.9.2 @sentry/browser: 5.0.5
This issue occurs when saving a Formik form, dispatching an action, which is then handled in Redux-Saga. Redux-Saga creates a saga, converts it to a promise, and then runs the promise as a Cloud Firestore transaction.
Based on the stack trace, it seems like an error is occurring in the new batch
method, which is sending the error up and getting caught in a componentDidCatch
function at the top of my app. This error is then being reported by Sentry. Here’s a small sample of the code I’m using… sadly, I don’t really have the time at the moment to create a repo that isolates the issue.
Saga code:
import { store } from '../../store/configureStore';
export function* runTransaction(transaction) {
const firebase = yield select(getFirebaseInstance);
const response = yield firebase.runTransactionSaga(store, transaction);
return response;
}
function* updateShowFlow() {
while (true) {
const { showId: id, show } = yield take(ShowActions.START_UPDATE_SHOW);
const firebase = yield select(getFirebaseInstance);
...other code and stuff
yield call(runTransaction, function* t() {
yield call([firebase.SDK.Shows, 'set'], showId, firebase.SDK.filter(showData, firebase.SDK.Shows.PublicMap));
yield call([firebase.SDK.Shows.Private(), 'set'], showId, firebase.SDK.filter(showData, firebase.SDK.Shows.PrivateMap));
});
...other code and stuff
}
}
Firestore code:
this.runTransactionSaga = async (store, callback) => {
const transactionResponse = await this.client.runTransaction(async (t) => {
TransactionManager.set(t);
return runSaga(store, callback).toPromise();
});
TransactionManager.unset();
return transactionResponse;
};
And the stack trace from the chrome console logger
breadcrumbs.js:81 RangeError: Maximum call stack size exceeded
at isUndefinedOrNull (index.js:29)
at objEquiv (index.js:46)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
at f66B.module.exports (index.js:25)
at objEquiv (index.js:98)
(anonymous) @ breadcrumbs.js:81
qh @ react-dom.production.min.js:4410
Eh.f.componentDidCatch.c.callback @ react-dom.production.min.js:4799
ih @ react-dom.production.min.js:4273
hh @ react-dom.production.min.js:4261
Vh @ react-dom.production.min.js:4985
Zh @ react-dom.production.min.js:5125
(anonymous) @ react-dom.production.min.js:5977
+wdc.exports.unstable_runWithPriority @ scheduler.production.min.js:276
Fi @ react-dom.production.min.js:5976
Di @ react-dom.production.min.js:5960
Yh @ react-dom.production.min.js:5927
Gi @ react-dom.production.min.js:5994
notify @ Subscription.js:23
notifyNestedSubs @ Subscription.js:65
notifySubscribers @ Provider.js:59
handleChangeWrapper @ Subscription.js:70
dispatch @ redux.js:216
(anonymous) @ redux-saga-core.esm.js:1421
(anonymous) @ middleware.js:36
dispatch @ redux.js:615
(anonymous) @ chunk-e922c950.js:136
(anonymous) @ redux-saga-core.esm.js:484
exec @ redux-saga-core.esm.js:30
flush @ redux-saga-core.esm.js:88
asap @ redux-saga-core.esm.js:45
runPutEffect @ redux-saga-core.esm.js:480
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
currCb @ redux-saga-core.esm.js:1257
end @ redux-saga-core.esm.js:1020
task.cont @ redux-saga-core.esm.js:845
next @ redux-saga-core.esm.js:1176
currCb @ redux-saga-core.esm.js:1257
Promise.then (async)
resolvePromise @ redux-saga-core.esm.js:407
runEffect @ redux-saga-core.esm.js:1202
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
currCb @ redux-saga-core.esm.js:1257
runSelectEffect @ redux-saga-core.esm.js:741
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
proc @ redux-saga-core.esm.js:1114
runCallEffect @ redux-saga-core.esm.js:544
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
currCb @ redux-saga-core.esm.js:1257
checkEnd @ chunk-e922c950.js:172
chCbAtKey @ chunk-e922c950.js:188
currCb @ redux-saga-core.esm.js:1257
Promise.then (async)
resolvePromise @ redux-saga-core.esm.js:407
runCallEffect @ redux-saga-core.esm.js:538
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
(anonymous) @ redux-saga-core.esm.js:683
runAllEffect @ redux-saga-core.esm.js:682
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
currCb @ redux-saga-core.esm.js:1257
(anonymous) @ redux-saga-core.esm.js:493
exec @ redux-saga-core.esm.js:30
flush @ redux-saga-core.esm.js:88
asap @ redux-saga-core.esm.js:45
chan.put @ redux-saga-core.esm.js:387
(anonymous) @ redux-saga-core.esm.js:1423
(anonymous) @ middleware.js:36
(anonymous) @ redux.js:465
onSubmit @ Edit.jsx:216
Formik._this.executeSubmit @ formik.esm.js:462
(anonymous) @ formik.esm.js:452
Promise.then (async)
Formik._this.submitForm @ formik.esm.js:442
Formik._this.handleSubmit @ formik.esm.js:429
ca @ react-dom.production.min.js:51
ja @ react-dom.production.min.js:71
ka @ react-dom.production.min.js:75
wa @ react-dom.production.min.js:142
Aa @ react-dom.production.min.js:171
ya @ react-dom.production.min.js:160
Da @ react-dom.production.min.js:234
Ad @ react-dom.production.min.js:1720
Gi @ react-dom.production.min.js:5992
Kb @ react-dom.production.min.js:662
Dd @ react-dom.production.min.js:1762
(anonymous) @ react-dom.production.min.js:6019
+wdc.exports.unstable_runWithPriority @ scheduler.production.min.js:276
Ii @ react-dom.production.min.js:6018
Cd @ react-dom.production.min.js:1739
sentryWrapped @ helpers.js:84
Show 5 more frames
VM80:1 Fetch finished loading: POST "https://sentry.io/api/1414499/store/?sentry_key=adbc85609ec74fa9ba7b1726cbe6f1f7&sentry_version=7".
(anonymous) @ VM80:1
(anonymous) @ fetch.js:37
step @ tslib.es6.js:210
(anonymous) @ tslib.es6.js:140
(anonymous) @ tslib.es6.js:113
__awaiter @ tslib.es6.js:90
FetchTransport.sendEvent @ fetch.js:23
BaseBackend.sendEvent @ basebackend.js:52
(anonymous) @ baseclient.js:402
onSuccess @ syncpromise.js:135
(anonymous) @ syncpromise.js:83
SyncPromise._executeHandlers @ syncpromise.js:82
SyncPromise._attachHandler @ syncpromise.js:96
(anonymous) @ syncpromise.js:113
SyncPromise @ syncpromise.js:100
SyncPromise.then @ syncpromise.js:112
(anonymous) @ baseclient.js:390
SyncPromise @ syncpromise.js:100
BaseClient._processEvent @ baseclient.js:389
(anonymous) @ baseclient.js:75
onSuccess @ syncpromise.js:135
(anonymous) @ syncpromise.js:83
SyncPromise._executeHandlers @ syncpromise.js:82
SyncPromise._attachHandler @ syncpromise.js:96
(anonymous) @ syncpromise.js:113
SyncPromise @ syncpromise.js:100
SyncPromise.then @ syncpromise.js:112
BaseClient.captureException @ baseclient.js:74
Hub._invokeClient @ hub.js:81
Hub.captureException @ hub.js:173
callOnHub @ index.js:20
captureException @ index.js:42
(anonymous) @ App.jsx:262
Hub.withScope @ hub.js:134
callOnHub @ index.js:20
withScope @ index.js:114
componentDidCatch @ App.jsx:258
Eh.f.componentDidCatch.c.callback @ react-dom.production.min.js:4800
ih @ react-dom.production.min.js:4273
hh @ react-dom.production.min.js:4261
Vh @ react-dom.production.min.js:4985
Zh @ react-dom.production.min.js:5125
(anonymous) @ react-dom.production.min.js:5977
+wdc.exports.unstable_runWithPriority @ scheduler.production.min.js:276
Fi @ react-dom.production.min.js:5976
Di @ react-dom.production.min.js:5960
Yh @ react-dom.production.min.js:5927
Gi @ react-dom.production.min.js:5994
notify @ Subscription.js:23
notifyNestedSubs @ Subscription.js:65
notifySubscribers @ Provider.js:59
handleChangeWrapper @ Subscription.js:70
dispatch @ redux.js:216
(anonymous) @ redux-saga-core.esm.js:1421
(anonymous) @ middleware.js:36
dispatch @ redux.js:615
(anonymous) @ chunk-e922c950.js:136
(anonymous) @ redux-saga-core.esm.js:484
exec @ redux-saga-core.esm.js:30
flush @ redux-saga-core.esm.js:88
asap @ redux-saga-core.esm.js:45
runPutEffect @ redux-saga-core.esm.js:480
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
currCb @ redux-saga-core.esm.js:1257
end @ redux-saga-core.esm.js:1020
task.cont @ redux-saga-core.esm.js:845
next @ redux-saga-core.esm.js:1176
currCb @ redux-saga-core.esm.js:1257
Promise.then (async)
resolvePromise @ redux-saga-core.esm.js:407
runEffect @ redux-saga-core.esm.js:1202
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
currCb @ redux-saga-core.esm.js:1257
runSelectEffect @ redux-saga-core.esm.js:741
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
proc @ redux-saga-core.esm.js:1114
runCallEffect @ redux-saga-core.esm.js:544
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
currCb @ redux-saga-core.esm.js:1257
checkEnd @ chunk-e922c950.js:172
chCbAtKey @ chunk-e922c950.js:188
currCb @ redux-saga-core.esm.js:1257
Promise.then (async)
resolvePromise @ redux-saga-core.esm.js:407
runCallEffect @ redux-saga-core.esm.js:538
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
(anonymous) @ redux-saga-core.esm.js:683
runAllEffect @ redux-saga-core.esm.js:682
runEffect @ redux-saga-core.esm.js:1210
digestEffect @ redux-saga-core.esm.js:1277
next @ redux-saga-core.esm.js:1167
currCb @ redux-saga-core.esm.js:1257
(anonymous) @ redux-saga-core.esm.js:493
exec @ redux-saga-core.esm.js:30
flush @ redux-saga-core.esm.js:88
asap @ redux-saga-core.esm.js:45
chan.put @ redux-saga-core.esm.js:387
(anonymous) @ redux-saga-core.esm.js:1423
(anonymous) @ middleware.js:36
(anonymous) @ redux.js:465
onSubmit @ Edit.jsx:216
Formik._this.executeSubmit @ formik.esm.js:462
(anonymous) @ formik.esm.js:452
Promise.then (async)
Formik._this.submitForm @ formik.esm.js:442
Formik._this.handleSubmit @ formik.esm.js:429
ca @ react-dom.production.min.js:51
ja @ react-dom.production.min.js:71
ka @ react-dom.production.min.js:75
wa @ react-dom.production.min.js:142
Aa @ react-dom.production.min.js:171
ya @ react-dom.production.min.js:160
Da @ react-dom.production.min.js:234
Ad @ react-dom.production.min.js:1720
Gi @ react-dom.production.min.js:5992
Kb @ react-dom.production.min.js:662
Dd @ react-dom.production.min.js:1762
(anonymous) @ react-dom.production.min.js:6019
+wdc.exports.unstable_runWithPriority @ scheduler.production.min.js:276
Ii @ react-dom.production.min.js:6018
Cd @ react-dom.production.min.js:1739
sentryWrapped @ helpers.js:84
Show 40 more frames
Issue Analytics
- State:
- Created 4 years ago
- Reactions:5
- Comments:15 (5 by maintainers)
Top GitHub Comments
I had the same issue. Only happens in production. Updating react-helmet
npm install --save react-helmet@6.0.0-beta
helps (https://github.com/nfl/react-helmet/issues/437#issuecomment-488805904)! Even though react-helmet wasn’t mentioned in any way in the error stack.Based on some googling, it looks like something else in your stack is doing a
deepEqual
on the resulting component. It came up with older versions of react-helmet, but others might be using it too.We now use
React.memo
on the wrapped component, which returns an object back. That has a very deeply nested structure, so deepEqual is recursing too far into the object tree. I don’t think there’s anything for us to do here.One thing to try is setting
pure: false
on the connect options and see if that fixes it. If so, then it’s definitely the issue I mentioned above. There still isn’t anything for us to do about that, since we’re returning a valid React component. But that would at least explain it and something for you to get a fix for from the library creating the error.