connect().subscribe: calling unsubscribe twice removes another listener
Maintainers usually reply within 1 day
@unknownhackerworld is already working on this.
Since Oct 26, 2026.
- #2138 by @unknownhackerworld — open
Assessment
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Newbie friendliness
- 25/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- react, redux, typescript
Research direction
Read extension/src/pageScript/api/index.ts, especially subscribe and the listener setup in connect(). The issue describes a reproduction and the expected fix: repeated calls to the returned unsubscribe function should leave other listeners intact. The author says a pull request with tests is ready, so check for existing work before taking this on.
Written by the indexing model from the issue text.
Description
Bug
Calling the unsubscribe function returned by connect().subscribe() a second time removes a different listener. Depending on what is registered, that is either another subscriber's listener or the extension's own internal listener for the connection, which then stops reacting to pause messages from the monitor.
Cause
subscribe in extension/src/pageScript/api/index.ts:
return function unsubscribe() {
const index = listenersForId.indexOf(liftedListener);
listenersForId.splice(index, 1);
};
After the first call the listener is no longer in the array, so indexOf returns -1. Array.prototype.splice(-1, 1) treats -1 as "the last element" and removes whatever listener is at the end of listeners[id].
listeners[id] starts as [rootListener] (set in connect()), and every subscribe() call pushes onto it. So:
- With two subscribers
[rootListener, a, b], callinga's unsubscribe twice removesb.bstops receiving monitor messages (DISPATCH,START,IMPORT, ...). - With one subscriber
[rootListener, a], callinga's unsubscribe twice removesrootListener. That listener handlesPAUSE_RECORDING(andSTART/STOPwhenautoPauseis on), so the pause button in the monitor no longer reaches the page and noLIFTEDreply is sent.
Calling an unsubscribe more than once is easy to hit from app code, for example a React effect cleanup that also runs on a manual disconnect, or a library that unsubscribes defensively. Redux's own store.subscribe treats a repeated unsubscribe as a no-op.
Reproduction
const devTools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ name: 'demo' });
const unsubscribeA = devTools.subscribe((m) => console.log('a', m.type));
devTools.subscribe((m) => console.log('b', m.type));
unsubscribeA();
unsubscribeA();
Now dispatch from the monitor (for example the "Dispatcher" or start/pause recording). Nothing is logged for b, although b never unsubscribed.
Suggested fix
Only call splice when the listener was found (index !== -1), so a repeated call is a no-op. I have a small PR with tests ready.
- Dominant language
- TypeScript
- Stars
- 14.4k
- Forks
- 1.2k
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 12
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from reduxjs/redux-devtools
-
Persist setting is lost when an instance is removedPossibly taken @RaphaelFakhri claimed this 25 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
reduxjs/redux-devtools#2126 ·
Maintainers usually reply within 1 day
-
feature
Difficulty 3/5 1-2 days Newbie friendliness 45/100
reduxjs/redux-devtools#2143 ·
Maintainers usually reply within 1 day
-
Memory leak in EdgeOpen
Difficulty 3/5 1-2 days Newbie friendliness 48/100
reduxjs/redux-devtools#2129 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 20/100
reduxjs/redux-devtools#2125 ·
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 52/100
reduxjs/redux-devtools#2091 ·
Maintainers usually reply within 1 day
All issues in reduxjs/redux-devtools
Similar issues
-
idea-scout idea:453
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
jeanibarz/agent-notebook#453 ·
Maintainers usually reply within 1 day
-
level/task
Difficulty 1/5 Under an hour Newbie friendliness 95/100
wazuh/wazuh-dashboard-plugins#9642 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 91/100
unicef/adt-studio#1112 ·
Maintainers usually reply within 2 days
-
feature request good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
TabularisDB/tabularis#1513 ·
Maintainers usually reply within 2 days
-
Difficulty 1/5 Under an hour Newbie friendliness 75/100