fix(config_flow): 🐛 explain which entry an already-configured abort collided with - #726
Merged
Merged
Conversation
…ollided with
- Split the serial lookup out of the unique-id check in
`_set_unique_id_or_abort`, so the abort log names the real cause instead
of the host: the previous message ("Device already configured: <host>")
pointed at the host while the match was actually on the serial-derived
unique_id, sending users hunting for a duplicate host in .storage.
- Add `_abort_already_configured`, which resolves the conflicting config
entry and reports it via a new `already_configured_serial` abort reason
with host/serial/existing entry placeholders. Since the unique_id is the
heat pump's serial number, a second endpoint aborting here means both
addresses reach the same controller - typically a duplicate port forward.
- Fall back to the generic `already_configured` reason when no stored entry
matches the serial (the conflict then came from an in-progress flow).
- Add the new string to en/de/nl/cs/pl; the generic `already_configured`
string stays placeholder-free for the core-raised DHCP abort path.
- The `LuxtronikSerialNumberError` handler was only reachable via the
evaluation order of `coordinator.unique_id` inside the shared `try`; it
now guards that lookup explicitly.
Refs #724
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nfigured_serial
- Hassfest rejects placeholders wrapped in single quotes ("the string should
not contain placeholders inside single quotes"), which failed CI on
'{existing_title}'.
- Drop the surrounding quotes in en/de/nl/cs/pl; the entry title still reads
clearly followed by its address in parentheses.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
🐛 Problem
Reported in #724: with three controllers behind one hostname on different port forwards, adding a second one aborts with "This device is already configured.", and the debug log says:
That message names the host, but the match is actually on the unique_id — which is the heat pump's serial number (
ID_WP_SerienNummer_DATUM/_HEX), with host and port playing no part. The reporter went looking for a duplicate host in.storage, found nothing, and had no way to see what actually collided.🔍 What this changes
Diagnostics only — the identity rule is unchanged. The unique_id stays the serial number, and two endpoints reporting the same serial still cannot both be configured. That is the correct invariant: the serial is the device identity, so a second endpoint with a known serial means both addresses reach the same controller (typically a duplicate port forward), not a second pump. Allowing both would mean two config entries polling one controller and two sets of entities contending over every write.
What changes is that the abort now says so:
and the user sees the same in the UI instead of the bare "This device is already configured."
🛠️ Implementation
_set_unique_id_or_abortsplits the serial lookup out of the unique-id check. Aside from enabling the above, this fixes theLuxtronikSerialNumberErrorhandler having been reachable only through the evaluation order ofcoordinator.unique_idinside the sharedtry._abort_already_configuredresolves the conflicting config entry and aborts with a newalready_configured_serialreason carrying{host},{serial},{existing_host}and{existing_title}.already_configured.already_configuredstring is left placeholder-free, since the DHCP path aborts through core's_abort_if_unique_id_configuredand would have nothing to substitute.🌍 Translations
already_configured_serialadded toen,de,nl,cs,pl, all with the same four placeholders.✅ Verification
config_flow.py205/205).ruff checkclean,ruff format --checkclean,basedpyright0 errors,codespellclean..github/scripts/check_translation_coverage.py: complete coverage, no placeholder drift across locales.This does not by itself close #724. It makes the cause visible, but which outcome is correct depends on something only the reporter can confirm: whether
:8450and:8452reach two physically distinct units. If they do — two units with identical factory serials — they will still be blocked and we would need a separate decision about identity. If, as the evidence suggests, both forwards reach one controller, this PR turns a confusing dead end into an actionable message.🤖 Generated with Claude Code