microg/GmsCore · error · IllegalStateException
Cannot remove OnSwitchChangeListener
Error message
Cannot remove OnSwitchChangeListener
What it means
Listener-contract guard in SwitchBar.removeOnSwitchChangeListener: the supplied listener is not currently registered, so there is nothing to remove — an unbalanced remove call (or a listener that was never added).
Source
Thrown at play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBar.java:192
mSwitchChangeListeners.get(n).onSwitchChanged(mSwitch, isChecked);
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
propagateChecked(isChecked);
}
public void addOnSwitchChangeListener(OnSwitchChangeListener listener) {
if (mSwitchChangeListeners.contains(listener)) {
throw new IllegalStateException("Cannot add twice the same OnSwitchChangeListener");
}
mSwitchChangeListeners.add(listener);
}
public void removeOnSwitchChangeListener(OnSwitchChangeListener listener) {
if (!mSwitchChangeListeners.contains(listener)) {
throw new IllegalStateException("Cannot remove OnSwitchChangeListener");
}
mSwitchChangeListeners.remove(listener);
}
static class SavedState extends BaseSavedState {
boolean checked;
boolean visible;
SavedState(Parcelable superState) {
super(superState);
}
/**
* Constructor called from {@link #CREATOR}
*/
private SavedState(Parcel in) {
super(in);
checked = (Boolean) in.readValue(Boolean.class.getClassLoader());View on GitHub (pinned to 157c9d86ac)
Solutions
- Only call removeOnSwitchChangeListener for listeners you know were added; track registration state yourself.
- Guard removal with a flag or check before calling.
- Make add/remove strictly paired in symmetric lifecycle callbacks (onCreate/onDestroy).
- Wrap in a null/empty check if the SwitchBar may have been torn down earlier.
Example fix
// before
switchBar.removeOnSwitchChangeListener(this);
// after
if (listenerRegistered) {
switchBar.removeOnSwitchChangeListener(this);
listenerRegistered = false;
} Defensive patterns
Strategy: validation
Validate before calling
if (listenerRegistered) switchBar.removeOnSwitchChangeListener(listener);
Try / catch
try { switchBar.removeOnSwitchChangeListener(listener); } catch (IllegalStateException e) { // not registered; ignore } Prevention
- Only remove listeners you added
- Guard with a registration flag
- Pair remove with the symmetric lifecycle callback
When it happens
Trigger: Calling removeOnSwitchChangeListener(listener) for a listener that was never added, or that was already removed (e.g. double invocation of a cleanup path, or cleanup running before setup).
Common situations: Calling remove in onDestroy when onCreate setup never ran (activity finished early); calling remove twice from two lifecycle paths; removing a different listener instance than the one added.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot add twice the same OnSwitchChangeListener
- Only one extension per type may be added
- DataSet has already been built.
- Must not be invoked on main thread
- Task is not yet complete
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/42a742f2137eb184.
Report an issue: GitHub.