GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Paginate list responses when multi requests are disabled by DevilRange · Pull Request #1838 · python-kasa/python-kasa

Conversation

@DevilRange

@DevilRange DevilRange commented Nov 5, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Fixes #1804. Probably also #1789 (same symptom on a KH100, no logs there to confirm).

One timeout on a batched request sets _multi_request_batch_size = 1 for the life of the protocol (#1759). _execute_multiple_query then takes the step == 1 branch, which never calls _handle_response_lists, so every list stops at its first page.

On a hub with more than 10 children, get_child_device_list returns 10 entries and the rest are removed as if unpaired, until the protocol is recreated. In Home Assistant the devices are deleted from the registry until the integration is reloaded (core#185809). #1802 stopped this for smartcam hubs by keeping batching on. SmartProtocol hubs (H100, KH100) still hit it.

Change

Drop the separate step == 1 send loop. With batching off, the requests go through the existing loop at the end of the method, which now paginates. That loop also handles lists requeried after an error in a batch, which were truncated the same way with no timeout involved.

  • A failed page raises instead of returning a short list, so no children are removed.
  • Complete lists cost no extra requests, so the P300 from Disable multi requests on timeout during multi-request #1759 is unaffected.
  • The one-way switch to single requests stays. The batch_size=1 config and the JSON decode fallback reach the same path, so pagination has to work here regardless.
  • A FORCE_SINGLE_REQUEST method no longer leaves an empty multipleRequest after the last batch (from ZeliardM's review). On SmartCamProtocol a lone scanApList or connectAp sent one on every call.

Testing

Ran this method on an H100 (firmware 1.7.10, 13 children) on 0.12.0. A real timeout logged Timeout during multi request, multi requests disabled. Requests with start_index=10 kept going, all 13 children stayed, and nothing went unavailable in the 9 minutes I logged after it. On stock 0.12.0 the same hub lost its last 3 children within seconds of that log line, and page 2 was never requested again.

The new parametrization and the two new tests fail without the change.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@DevilRange
Paginate list responses when multi requests are disabled
da8fcf1
After a timeout disables multi requests, _execute_multiple_query returned
from a separate single request branch that never fetched further list pages.
A hub with more than 10 children then lost the children past the first page
until the protocol was recreated.

Remove that branch and send the requests from the existing loop at the end of
the method, which now paginates. Lists requeried after an error in a batch had
the same truncation and are fixed by this too.
@codecov

codecov Bot commented Nov 5, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.49%. Comparing base (9478ed2) to head (185b022).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1838      +/-   ##
==========================================
- Coverage   93.49%   93.49%   -0.01%     
==========================================
  Files         161      161              
  Lines       10169    10166       -3     
  Branches     1053     1053              
==========================================
- Hits         9508     9505       -3     
  Misses        469      469              
  Partials      192      192              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

This was referenced Nov 5, 2026
H200 firmware 1.7.7 intermittently returns only 10/22 children; missing children are removed until reload #1804
Open
Tapo T310 sensors disappear from HA until integration reload home-assistant/core#185809
Open
@rytilahti rytilahti added the bug Something isn't working label Nov 5, 2026
@jimjaeger jimjaeger mentioned this pull request Nov 5, 2026
TP-Link KH100 hub: the same 5 of 15 child devices are repeatedly removed from HA home-assistant/core#190720
Open
@rytilahti rytilahti mentioned this pull request Nov 6, 2026
TP-Link Tapo H200 child devices disappear from Home Assistant until integration is reconfigured home-assistant/core#186473
Closed
ZeliardM
ZeliardM reviewed Nov 6, 2026
View reviewed changes
Comment thread kasa/protocols/smartprotocol.py Outdated
Comment on lines +225 to +228
step = self._multi_request_batch_size
if step == 1:
# If step is 1 do not send request batches
for request in multi_requests:
method = request["method"]
req = self.get_smart_request(method, request.get("params"))
resp = await self._transport.send(req)
self._handle_response_error_code(
resp, method, raise_on_error=raise_on_error
)
multi_result[method] = resp["result"]
return multi_result

for batch_num, i in enumerate(range(0, end, step)):
# If step is 1 do not send batches, the loop at the end sends single requests
batch_starts = range(0, end, step) if step != 1 else ()
for batch_num, i in enumerate(batch_starts):

@ZeliardM ZeliardM Nov 6, 2026

Copy link
Copy Markdown
Collaborator

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.

Suggested change
step = self._multi_request_batch_size
if step == 1:
# If step is 1 do not send request batches
for request in multi_requests:
method = request["method"]
req = self.get_smart_request(method, request.get("params"))
resp = await self._transport.send(req)
self._handle_response_error_code(
resp, method, raise_on_error=raise_on_error
)
multi_result[method] = resp["result"]
return multi_result
for batch_num, i in enumerate(range(0, end, step)):
# If step is 1 do not send batches, the loop at the end sends single requests
batch_starts = range(0, end, step) if step != 1 else ()
for batch_num, i in enumerate(batch_starts):
step = self._multi_request_batch_size
if step == 1:
# Batching is off, so the loop at the end sends each request on its own
multi_requests = []
for batch_num, i in enumerate(range(0, len(multi_requests), step)):

This might read a little plainer than the conditional range. Counting to len(multi_requests) instead of end also stops an empty multipleRequest from going out when a FORCE_SINGLE_REQUEST method is in the query (5 methods plus scanApList at batch size 5, for example), which happens on master too. The full suite passes with it.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@DevilRange DevilRange Nov 6, 2026

Copy link
Copy Markdown
Author

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.

Applied, thanks. Same thing on SmartCamProtocol for a lone scanApList or connectAp: end is 1 and multi_requests is empty, so wifi_scan and wifi_join sent an empty multipleRequest first. Added a test for the 5 + scanApList case. Checked against the fake transport only, not a real camera.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@DevilRange @ZeliardM
Do not send an empty multipleRequest for single request methods
185b022
The batch loop counted FORCE_SINGLE_REQUEST methods, so it could send an empty
batch. On SmartCamProtocol a lone scanApList or connectAp always sent one.

Co-authored-by: ZeliardM <[email protected]>
@renero82

renero82 commented Nov 9, 2026

Copy link
Copy Markdown

Another H100 confirmation, on python-kasa 0.12.0 / Home Assistant 2026.11.0.

The hub has 16 children. After Timeout during multi request, multi requests disabled, every update returns start_index 0, sum 16 with only 10 entries, and the same 6 children are removed (Removed child device ...) with no warning or error logged. Page 2 is never requested again until the config entry is reloaded. In about 25 hours the hub lost them roughly 70 times, every 1 to 5 minutes during the night, and each time an automation had to reload the entry. My three other hubs have 6 children each and never lose any.

This matches the analysis in #1804, and the change in this PR targets exactly the step == 1 branch where it happens. I'd be glad to see it merged and released so Home Assistant can pick it up.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ZeliardM ZeliardM ZeliardM left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

bug Something isn't working

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

H200 firmware 1.7.7 intermittently returns only 10/22 children; missing children are removed until reload

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@DevilRange @renero82 @ZeliardM @rytilahti
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.