-
Notifications
You must be signed in to change notification settings - Fork 11
Fix StopIteration crash when lock has unmanaged slots with masked PINs #760
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
When a lock has code slots with masked PINs (all *'s) that aren't managed by Lock Code Manager, the async_get_usercodes() function would crash with "RuntimeError: coroutine raised StopIteration". This occurred because the code tried to find a matching LCM config entry for every slot on the lock, but slots not managed by LCM have no corresponding config entry. The fix adds an early check: if the slot isn't in the configured code_slots, we record an empty string and skip the config entry lookup entirely. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes CI conflict with HA 2026.1.0 final release. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a RuntimeError: coroutine raised StopIteration crash that occurred when a Z-Wave JS lock has code slots with masked PINs (all *'s) that are not managed by Lock Code Manager. The bug was caused by attempting to find a matching LCM config entry for unmanaged slots using next(), which raised StopIteration when no match was found.
Key changes:
- Added early validation to skip config entry lookup for unmanaged slots with masked PINs
- Added regression test to prevent this issue from recurring
- Removed redundant conditional check around logging statement
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| custom_components/lock_code_manager/providers/zwave_js.py | Added early return logic to handle unmanaged slots with masked PINs, preventing StopIteration from being raised |
| tests/providers/test_zwave_js.py | Added comprehensive regression test that verifies the fix by testing both managed and unmanaged slots with masked PINs |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Fixes CI test failures with pytest-asyncio 1.3.0 that occur due to
event loop scoping issues ("Timeout context manager should be used
inside a task").
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The autouse=True on the aiohttp_client override was causing event loop scoping issues in CI with pytest-asyncio 1.3.0. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #760 +/- ##
==========================================
- Coverage 93.21% 93.13% -0.08%
==========================================
Files 29 29
Lines 2357 2359 +2
Branches 77 77
==========================================
Hits 2197 2197
- Misses 160 162 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Proposed change
When a lock has code slots with masked PINs (all
*'s) that aren't managed by Lock Code Manager, theasync_get_usercodes()function would crash withRuntimeError: coroutine raised StopIteration.This occurred because the code iterated over ALL slots from the lock's cache, but the
next()call at line 434 tried to find a matching LCM config entry for each slot. Slots not managed by LCM have no corresponding config entry, causingStopIterationto be raised inside the async function, which Python 3.7+ converts toRuntimeError.The fix adds an early check: if the slot isn't in the configured
code_slots, we record an empty string and skip the config entry lookup entirely.Also adds a regression test to prevent this from recurring.
Type of change
Additional information
🤖 Generated with Claude Code