Tencent/matrix · error · IllegalStateException

Illegal battery state

Error message

Illegal battery state: <action>

What it means

dispatchBatteryStateChangedEvent(action) throws IllegalStateException for any battery-state broadcast action it does not recognize. It only handles the known set of ACTION_BATTERY_CHANGED-derived events (charging/discharging/full/not-charging etc.); an unknown action string falls into the terminal else branch.

Solutions

  1. Only dispatch actions produced by the delegate's own parsing layer; filter out unhandled actions before calling.
  2. Add a whitelist check: if the action is not one of the supported BatteryState events, ignore it instead of dispatching.
  3. Upgrade the Matrix battery-canary version if a new platform action must be supported.

Example fix

// before
@Override
public void onReceive(Context ctx, Intent i) {
    delegate.dispatchBatteryStateChangedEvent(i.getAction()); // throws for LOW/OKAY
}

// after
@Override
public void onReceive(Context ctx, Intent i) {
    String action = i.getAction();
    if (BatteryManager.ACTION_BATTERY_CHANGED.equals(action)) {
        delegate.dispatchBatteryStateChangedEvent(action);
    }
}
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<String> SUPPORTED = new HashSet<>(Arrays.asList(
    BatteryManager.ACTION_BATTERY_CHANGED /* + delegate-supported actions */));

if (!SUPPORTED.contains(action)) return; // ignore unknown battery actions

Try / catch

try {
    delegate.dispatchBatteryStateChangedEvent(action);
} catch (IllegalStateException e) {
    MatrixLog.w(TAG, "unsupported battery action: " + action);
}

Prevention

When it happens

Trigger: Calling onBatteryChangeEvent(...) or the async run() path with a battery state action string outside the supported set (e.g. ACTION_BATTERY_LOW / ACTION_BATTERY_OKAY, or a vendor-patched action), which is then forwarded to dispatchBatteryStateChangedEvent.

Common situations: Forwarding raw BroadcastReceiver actions (BatteryManager.ACTION_BATTERY_LOW, ACTION_POWER_CONNECTED) directly into the delegate; OEM ROMs emitting custom battery actions; forwarding an event from a different Android version with changed action strings.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/7163f79bd4c9b0ce. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/BatteryEventDelegate.java:428

    }

    @VisibleForTesting
    void dispatchBatteryStateChangedEvent(Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_BATTERY_OKAY.equals(action) || Intent.ACTION_BATTERY_LOW.equals(action)) {
            MatrixLog.i(TAG, "onBatteryStateChanged >> " + action);
            synchronized (mListenerList) {
                BatteryState batteryState = currentState();
                for (Listener item : mListenerList) {
                    if (item instanceof Listener.ExListener) {
                        if (((Listener.ExListener) item).onBatteryStateChanged(batteryState, Intent.ACTION_BATTERY_LOW.equals(action))) {
                            removeListener(item);
                        }
                    }
                }
            }
        } else {
            throw new IllegalStateException("Illegal battery state: " + action);
        }
    }

    @VisibleForTesting
    void dispatchBatteryPowerChanged(int pct) {
        MatrixLog.i(TAG, "onBatteryPowerChanged >> " + pct + "%");
        synchronized (mListenerList) {
            BatteryState batteryState = currentState();
            for (Listener item : mListenerList) {
                if (item instanceof Listener.ExListener) {
                    if (((Listener.ExListener) item).onBatteryPowerChanged(batteryState, pct)) {
                        removeListener(item);
                    }
                }
            }
        }
    }

View on GitHub (pinned to 3b8293bd65)