Skip to content

fix: guard config flow against empty account list#25

Merged
virtitnerd merged 4 commits into
mainfrom
fix/config-flow-empty-account-guard
May 24, 2026
Merged

fix: guard config flow against empty account list#25
virtitnerd merged 4 commits into
mainfrom
fix/config-flow-empty-account-guard

Conversation

@virtitnerd
Copy link
Copy Markdown
Owner

@virtitnerd virtitnerd commented May 24, 2026

What

If get_linked_accounts() returns an empty list (login succeeds but the profile has no billing accounts), the config flow previously fell through silently to an empty account-selection screen. The user would see an empty checklist, be unable to select anything, and hit no_accounts_selected in an unbreakable loop with no path forward.

This PR adds an explicit guard:

  • async_step_user: if accounts list is empty after successful auth, log an error and re-display the credentials form with a no_accounts_found error message
  • async_step_reconfigure: same guard for the reconfigure path

Changes

  • config_flow.py — empty-list check after _fetch_accounts() in both steps
  • strings.json / translations/en.json — new no_accounts_found error key
  • tests/test_config_flow.py — two new tests covering both paths

Test plan

  • pytest tests/test_config_flow.py passes
  • ruff check / ruff format --check clean
  • 100% coverage maintained

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Validate that linked billing accounts exist after successful login; setup and reconfigure flows now abort with a clear "no accounts found" error to avoid empty selection screens.
  • Localization
    • Added a new user-facing error message for the "no accounts found" scenario.
  • Tests
    • Added tests covering login-without-linked-accounts for initial setup and reconfiguration.

Review Change Stack

virtitnerd and others added 2 commits May 23, 2026 21:11
If get_linked_accounts() returns [] (login succeeds but no accounts
on the profile), the user_step and reconfigure_step now return an
error instead of silently falling through to an empty selection
screen where no_accounts_selected fires in an unbreakable loop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the error string referenced by the empty-account guard added
in the previous commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f17453c0-38cc-474e-a894-a0f6a9d5eb51

📥 Commits

Reviewing files that changed from the base of the PR and between 9fc9b6f and 9f0eac8.

📒 Files selected for processing (1)
  • custom_components/national_grid/config_flow.py

📝 Walkthrough

Walkthrough

The config flow now aborts when authentication succeeds but the API returns no linked accounts; a new localized error string and tests cover the initial user and reconfigure flows.

Changes

Empty Account Validation and Error Handling

Layer / File(s) Summary
Error message translation
custom_components/national_grid/strings.json, custom_components/national_grid/translations/en.json
Added config.error.no_accounts_found translation for the case where login succeeds but no billing accounts are found.
Config flow empty-account checks
custom_components/national_grid/config_flow.py
async_step_user and async_step_reconfigure now check _accounts after _fetch_accounts; if empty, they log and abort the flow with reason="no_accounts_found".
Tests for empty-account scenarios
tests/test_config_flow.py
Added test_user_step_no_accounts_found and test_reconfigure_no_accounts_found, asserting both flows abort with reason == "no_accounts_found" when get_linked_accounts returns an empty list.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped in to check each login round,
Found no linked accounts upon the ground,
I logged the silence and gently frowned,
Aborted the flow so none confound,
Tests sing the change and errors are sound.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: guard config flow against empty account list' directly and clearly describes the main change: adding validation to prevent the config flow from proceeding when no accounts are returned, matching the core purpose of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/config-flow-empty-account-guard

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
custom_components/national_grid/config_flow.py (1)

59-64: 💤 Low value

Consider abort flow instead of error for better UX.

When no_accounts_found occurs, the user cannot resolve it by re-entering credentials since authentication already succeeded. An abort with reason no_accounts_found might provide clearer UX, indicating the user must add accounts through National Grid before configuring this integration.

Current implementation is functional and the error message does clarify the situation, so this is optional.

Alternative approach using abort
             else:
                 if not self._accounts:
                     _LOGGER.error(
                         "Login succeeded but no accounts returned for %s",
                         self._username,
                     )
-                    _errors["base"] = "no_accounts_found"
+                    return self.async_abort(reason="no_accounts_found")
                 else:

Note: This would also require adding no_accounts_found to the abort section in strings.json rather than error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@custom_components/national_grid/config_flow.py` around lines 59 - 64, Replace
the current error path that sets _errors["base"]="no_accounts_found" when
self._accounts is empty with an abort flow so the config flow stops with a clear
reason; locate the block referencing self._accounts, _LOGGER and _username and
instead call the flow abort helper (e.g., self.async_abort or
self._abort_if_unique with reason "no_accounts_found") so the UI shows an abort
page (remember to add "no_accounts_found" to the abort strings in strings.json)
while keeping the existing log line for diagnostics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@custom_components/national_grid/config_flow.py`:
- Around line 59-64: Replace the current error path that sets
_errors["base"]="no_accounts_found" when self._accounts is empty with an abort
flow so the config flow stops with a clear reason; locate the block referencing
self._accounts, _LOGGER and _username and instead call the flow abort helper
(e.g., self.async_abort or self._abort_if_unique with reason
"no_accounts_found") so the UI shows an abort page (remember to add
"no_accounts_found" to the abort strings in strings.json) while keeping the
existing log line for diagnostics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 715cb30e-6924-41d7-81c8-42719fd60893

📥 Commits

Reviewing files that changed from the base of the PR and between 8359c3a and 7568e06.

📒 Files selected for processing (4)
  • custom_components/national_grid/config_flow.py
  • custom_components/national_grid/strings.json
  • custom_components/national_grid/translations/en.json
  • tests/test_config_flow.py

Showing a form error when login succeeds but the profile has no
accounts implies the user can fix it by editing credentials.
An abort page is semantically correct: the flow cannot proceed
and there is nothing to retry.

Moves the no_accounts_found key from config.error to config.abort
in both strings files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
custom_components/national_grid/config_flow.py (1)

60-63: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid logging raw usernames in error paths.

Line 61 and Line 147 log the full username, which can leak PII (often email) into logs. Prefer a redacted value or remove the identifier from the message.

Proposed fix
-                    _LOGGER.error(
-                        "Login succeeded but no accounts returned for %s",
-                        self._username,
-                    )
+                    _LOGGER.error(
+                        "Login succeeded but no linked accounts were returned",
+                    )
...
-                    _LOGGER.error(
-                        "Reconfigure: login succeeded but no accounts returned for %s",
-                        reconfigure_entry.data[CONF_USERNAME],
-                    )
+                    _LOGGER.error(
+                        "Reconfigure: login succeeded but no linked accounts were returned",
+                    )

Also applies to: 146-149

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@custom_components/national_grid/config_flow.py` around lines 60 - 63, The
error logs currently call _LOGGER.error with self._username which can leak PII;
update both occurrences (the _LOGGER.error call referencing self._username and
the similar one around lines 146-149) to either remove the username from the
message or log a redacted version (e.g., mask most characters or only show a
non-PII suffix/prefix) before passing it to _LOGGER.error; locate the calls by
searching for _LOGGER.error(...) that reference self._username in the
config_flow.py methods handling login/results and replace them with a safe,
redacted identifier or omit the identifier entirely.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@custom_components/national_grid/config_flow.py`:
- Around line 60-63: The error logs currently call _LOGGER.error with
self._username which can leak PII; update both occurrences (the _LOGGER.error
call referencing self._username and the similar one around lines 146-149) to
either remove the username from the message or log a redacted version (e.g.,
mask most characters or only show a non-PII suffix/prefix) before passing it to
_LOGGER.error; locate the calls by searching for _LOGGER.error(...) that
reference self._username in the config_flow.py methods handling login/results
and replace them with a safe, redacted identifier or omit the identifier
entirely.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 310b70fa-4027-4bdc-8585-a86c5e092c4c

📥 Commits

Reviewing files that changed from the base of the PR and between 7568e06 and 9fc9b6f.

📒 Files selected for processing (4)
  • custom_components/national_grid/config_flow.py
  • custom_components/national_grid/strings.json
  • custom_components/national_grid/translations/en.json
  • tests/test_config_flow.py
✅ Files skipped from review due to trivial changes (1)
  • custom_components/national_grid/translations/en.json

Log messages recording "no accounts returned" passed the username
(an email address) as a format argument, which would appear in HA
log files and diagnostics exports. Drop the argument — the message
is diagnostic without identifying the account holder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@virtitnerd virtitnerd merged commit c6d39a7 into main May 24, 2026
7 checks passed
@virtitnerd virtitnerd deleted the fix/config-flow-empty-account-guard branch May 24, 2026 19:51
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.

1 participant