Skip to content

[codex] Handle retryable SleepIQ login failures#168522

Draft
anderbak wants to merge 3 commits intohome-assistant:devfrom
anderbak:codex/sleepiq-retryable-login-failures
Draft

[codex] Handle retryable SleepIQ login failures#168522
anderbak wants to merge 3 commits intohome-assistant:devfrom
anderbak:codex/sleepiq-retryable-login-failures

Conversation

@anderbak
Copy link
Copy Markdown

Summary

  • only treat SleepIQLoginException("Incorrect username or password") as invalid auth
  • treat other SleepIQLoginException values during setup and config flow as retryable connection failures
  • add regression coverage for both setup and flow behavior

Why

asyncsleepiq uses SleepIQLoginException for both real credential failures and transient login/connection failures such as:

Connection failure: Cannot connect to host prod-api.sleepiq.sleepnumber.com:443 ssl:default [DNS server returned general failure]

Home Assistant currently maps all of those exceptions to invalid_auth / reauth, which prompts users to re-enter valid credentials during transient provider or DNS outages.

Impact

Transient SleepIQ login failures should now retry automatically instead of triggering reauth, while true bad credentials still surface as auth errors.

Testing

  • python -m py_compile homeassistant/components/sleepiq/__init__.py homeassistant/components/sleepiq/config_flow.py tests/components/sleepiq/test_init.py tests/components/sleepiq/test_config_flow.py
  • full pytest not run locally; this machine only has Python 3.12 while current core dev requires Python 3.14.2+

Copilot AI review requested due to automatic review settings April 19, 2026 00:13
Copy link
Copy Markdown

@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

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

Hi @anderbak

It seems you haven't yet signed a CLA. Please do so here.

Once you do that we will be able to review and accept this pull request.

Thanks!

@home-assistant
Copy link
Copy Markdown

Hey there @mfugate1, @kbickar, mind taking a look at this pull request as it has been labeled with an integration (sleepiq) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of sleepiq can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant mark-draft Mark the pull request as draft.
  • @home-assistant ready-for-review Remove the draft status from the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign sleepiq Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant update-branch Update the pull request branch with the base branch.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) on the pull request.

Copy link
Copy Markdown
Contributor

Copilot AI left a 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 updates the SleepIQ integration’s error mapping so only truly invalid credentials trigger invalid_auth/reauth, while other SleepIQLoginException login failures are treated as retryable connection failures.

Changes:

  • Add logic to classify SleepIQLoginException("Incorrect username or password") as invalid auth, and treat other login exceptions as connection issues (retryable during setup; cannot_connect in config flow).
  • Update config entry setup to raise ConfigEntryNotReady for retryable login exceptions instead of ConfigEntryAuthFailed.
  • Add regression tests covering setup retry vs setup error, and config flow invalid auth vs cannot connect.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
homeassistant/components/sleepiq/__init__.py Distinguishes invalid-credential login failures from retryable login failures during config entry setup.
homeassistant/components/sleepiq/config_flow.py Updates try_connection to map only the credential error to invalid_auth, other login failures to cannot_connect.
tests/components/sleepiq/test_init.py Adds tests asserting SETUP_ERROR for invalid auth and SETUP_RETRY for retryable login failures/timeouts.
tests/components/sleepiq/test_config_flow.py Adds parametrized coverage for invalid auth vs cannot connect on login failures.

Comment on lines +56 to +59
def _is_invalid_auth(err: SleepIQLoginException) -> bool:
"""Return if a SleepIQ login exception indicates invalid credentials."""
return "incorrect username or password" in str(err).lower()

Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

Centralize the invalid-auth detection logic in a single shared helper/constant (e.g., in const.py or a small util module) to avoid the duplicated _is_invalid_auth implementation diverging between __init__.py and config_flow.py over time.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +24


def _is_invalid_auth(err: SleepIQLoginException) -> bool:
"""Return if a SleepIQ login exception indicates invalid credentials."""
return "incorrect username or password" in str(err).lower()
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

Avoid duplicating _is_invalid_auth in multiple modules; move the credential-error string match into a shared helper/constant so config flow and entry setup stay consistent if the upstream error text ever changes.

Suggested change
def _is_invalid_auth(err: SleepIQLoginException) -> bool:
"""Return if a SleepIQ login exception indicates invalid credentials."""
return "incorrect username or password" in str(err).lower()
_INVALID_AUTH_ERROR = "incorrect username or password"
def _is_invalid_auth(err: SleepIQLoginException) -> bool:
"""Return if a SleepIQ login exception indicates invalid credentials."""
return _INVALID_AUTH_ERROR in str(err).lower()

Copilot uses AI. Check for mistakes.
Comment on lines 124 to 129
await gateway.login(user_input[CONF_USERNAME], user_input[CONF_PASSWORD])
except SleepIQLoginException:
return "invalid_auth"
except SleepIQLoginException as err:
if _is_invalid_auth(err):
return "invalid_auth"
return "cannot_connect"
except SleepIQTimeoutException:
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

Add regression coverage for the reauth flow’s failure cases since try_connection now maps SleepIQLoginException to either invalid_auth or cannot_connect and reauth uses the same helper.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 20, 2026 22:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment on lines +127 to +139
@pytest.mark.parametrize(
("side_effect", "error"),
[
(
SleepIQLoginException("Incorrect username or password"),
"invalid_auth",
),
(
SleepIQLoginException("Connection failure: Cannot connect to host"),
"cannot_connect",
),
(SleepIQTimeoutException, "cannot_connect"),
],
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

Reduce duplicated parametrization data by extracting the shared (side_effect, error) cases into a single constant/fixture and reusing it in both test_login_failure and test_reauth_failure to keep future updates in sync.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants