actuallymentor / battery

CLI for managing the battery charging status for M1 Macs
MIT License
3.22k stars 140 forks source link

Battery app pops up a GUI alert message stating "Battery limiter error: Cannot read properties of undefined (reading 'includes')" #273

Open johnmcdowell opened 2 months ago

johnmcdowell commented 2 months ago

What is the issue? (required) Battery app pops up a GUI alert message stating "Battery limiter error: Cannot read properties of undefined (reading 'includes')"

Further, I don't think the app is logging the output of its call to battery status_csv in some case where that call does not return expected output.

What exactly did you do to produce the issue? (required) Steps to reproduce the behavior:

  1. Let computer hibernate/deep sleep from low battery.
  2. Plug in computer and log in
  3. Observe GUI error stating "Battery limiter error: Cannot read properties of undefined (reading 'includes')" and logs below.

I'm not sure I can repro this consistently, but the app normally works and the error is intermittent.

Expected behavior (required) Not see a GUI error message at log-in.

Error logs

[ update-electron-app ] 
checking-for-update
Executing PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew battery status_csv
Battery status: 
{"percentage":"??","remaining":"unknown","charging":false,"discharging":false,"battery_state":"??% (unknown remaining)","daemon_state":"smc charging disabled"}
Setting interface refresh speed to 0.5 minutes
Battery status: 
{"percentage":"??","remaining":"unknown","charging":false,"discharging":false,"battery_state":"??% (unknown remaining)","daemon_state":"smc charging disabled"}
Executing PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew battery status
[ update-electron-app ] 
updater error
[ update-electron-app ] 
Error: The Internet connection appears to be offline.
Executing PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew battery status_csv
Executing PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew battery status_csv
Generate app menu percentage: ?? (discharge disallowed, limited off)
Error getting battery status: 
TypeError: Cannot read properties of undefined (reading 'includes')
Display percentage NaN based on NaN
Get active logo for ??
🚨 Missing image: /Applications/battery.app/Contents/Resources/battery-inactive-NaN-Template.png
Refreshing interface update timer
Resetting interface timer speed
Executing PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew battery status_csv
Refreshing tray icon...
Battery status: 
{"percentage":"??","remaining":"unknown","charging":false,"discharging":false,"battery_state":"??% (unknown remaining)","daemon_state":"smc charging disabled"}
Setting interface refresh speed to 0.5 minutes
Executing PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew battery status_csv
Executing PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew battery status
Battery status: 
{"percentage":"??","remaining":"unknown","charging":false,"discharging":false,"battery_state":"??% (unknown remaining)","daemon_state":"smc charging disabled"}
Limiter status message: 

Refreshing interface update timer
Refreshing tray icon...
Force discharge setting: undefined undefined
[ update-electron-app ] 
checking-for-update
Battery status: 
{"percentage":"21","remaining":"2:01","charging":true,"discharging":false,"maintain_percentage":"80","battery_state":"21% (2:01 remaining)","daemon_state":"smc charging enabled"}
Executing PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew battery status
Battery status: 
{"percentage":"21","remaining":"2:01","charging":true,"discharging":false,"maintain_percentage":"80","battery_state":"21% (2:01 remaining)","daemon_state":"smc charging enabled"}
Setting interface refresh speed to 0.5 minutes
Limiter status message: 
05/13/24-11:30:06 - Battery at 21% (2:01 remaining), smc charging enabled
05/13/24-11:30:06 - Your battery is currently being maintained at 80%

Get active logo for ??
Generate app menu percentage: ?? (discharge disallowed, limited on)
🚨 Missing image: /Applications/battery.app/Contents/Resources/battery-active-NaN-Template.png
johnmcdowell commented 2 months ago

I tried to debug the issue with the logs.

I think there is a case here where exec_async can resolve a promise with an undefined value if battery status prints nothing to stdout. I assume there's an assumption that that should never happen, but how else could message be undefined here?

const is_limiter_enabled = async () => {

    try {
        const message = await exec_async( `${ battery } status` )
        log( `Limiter status message: `, message )
        return message.includes( 'being maintained at' )

Just a potential related thought about the logging: I also wonder if there shouldn't be a log entry in the case that the message from battery status_csv is undefined here, rather than just silently assigning empty values? Though perhaps that doesn't help us understand the root of the issue.

const get_battery_status = async () => {

    try {
        const message = await exec_async( `${ battery } status_csv` )
        let [ percentage='??', remaining='', charging='', discharging='', maintain_percentage='' ] = message?.split( ',' ) || []

All that said, I don't understand if I'm seeing the popup alert after hibernation because of something that needs to be fixed deeper down, or if instead that GUI alert should suppressed in some cases.

Hope this helps.