Skip to content

Guard against getESSList() returning None ('NoneType' object is not iterable)#25

Merged
CharlesGillanders merged 2 commits into
CharlesGillanders:mainfrom
szrudi:fix/guard-none-esslist
Jun 5, 2026
Merged

Guard against getESSList() returning None ('NoneType' object is not iterable)#25
CharlesGillanders merged 2 commits into
CharlesGillanders:mainfrom
szrudi:fix/guard-none-esslist

Conversation

@szrudi

@szrudi szrudi commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Problem

getESSList() is declared -> Optional[list] and legitimately returns None whenever the underlying api_get() receives a non-success / empty payload or the Alpha ESS cloud is briefly unreachable (connection timeout, Cannot connect to host openapi.alphaess.com).

But getdata() and authenticate() iterate the result without a None check:

units = await self.getESSList()
for idx, unit in enumerate(units):   # 'NoneType' object is not iterable when units is None

So any time getESSList() returns None, the entire poll raises 'NoneType' object is not iterable (logged under the alphaess.alphaess logger and re-raised). Observed in the wild on a transient cloud hiccup:

ERROR [alphaess.alphaess] Connection timeout to host https://openapi.alphaess.com/api/getEssList
ERROR [alphaess.alphaess] Error: Connection timeout to host https://openapi.alphaess.com/api/getEssList when calling ...
ERROR [alphaess.alphaess] 'NoneType' object is not iterable
WARNING [custom_components.alphaess] Cloud API error: 'NoneType' object is not iterable

(The Home Assistant integration catches it downstream and falls back, but the library shouldn't throw on a return value its own type hint declares possible.)

Fix

Guard both iteration sites against None:

  • getdata() logs a warning and returns the (empty) alldata list, so the caller keeps its previous data instead of crashing.
  • authenticate() returns False.

No behavioural change when the API responds normally.

When the Alpha ESS API returns a non-success or empty payload (e.g.
{'code': 6026, 'msg': 'network is busy', 'data': None}, or any response
where data is null), api_get() logs it and returns None, so getESSList()
returns None.

getdata() and authenticate() then iterate `units` directly:

    units = await self.getESSList()
    for idx, unit in enumerate(units):   # 'NoneType' object is not iterable

raising "'NoneType' object is not iterable" (logged under the
alphaess.alphaess logger and re-raised) on every affected poll. This is a
transient cloud condition, so guard both call sites to skip the cycle
gracefully instead of throwing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@CharlesGillanders CharlesGillanders left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@CharlesGillanders CharlesGillanders dismissed their stale review June 5, 2026 09:47

Approved too soon

@CharlesGillanders CharlesGillanders self-requested a review June 5, 2026 09:48

@CharlesGillanders CharlesGillanders left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, I'm happy to accept it but could please also edit setup.py to bump the version number?

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@szrudi

szrudi commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the quick review! Bumped setup.py to 0.0.19 in the latest commit. Let me know if there's anything else you'd like changed.

@CharlesGillanders CharlesGillanders self-requested a review June 5, 2026 13:53
@CharlesGillanders CharlesGillanders merged commit 4ff7a14 into CharlesGillanders:main Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants