Skip to content

fix: prevent duplicate config form in editor (async _renderEditor race condition) - #10

Open
eliseo-juan wants to merge 3 commits into
mainfrom
claude/fix-card-config-duplication-QrIPD
Open

fix: prevent duplicate config form in editor (async _renderEditor race condition)#10
eliseo-juan wants to merge 3 commits into
mainfrom
claude/fix-card-config-duplication-QrIPD

Conversation

@eliseo-juan

Copy link
Copy Markdown
Owner

Summary

Fixes a regression introduced in PR #8 where the card editor rendered the configuration form twice, making it unusable.

  • Root cause: PR Add provider instance filtering for Music Assistant playlists #8 changed _renderEditor() to async to support await _fetchProviders(), but didn't guard against concurrent calls. Multiple callers (setConfig, set hass, and the value-changed handler) could all trigger _renderEditor() simultaneously. Each call resets shadow.innerHTML at the top, then yields at the await. When both resume, they both find the same live #form-host and each append their own ha-form — resulting in duplicated config fields and two independent event listeners firing config-changed.
  • Fix 1: Generation counter _renderGen — incremented on every call, checked after the await. Stale renders abort before touching the DOM.
  • Fix 2: Added missing provider_instance: '' default to editor.js setConfig, aligning it with card.js so the provider dropdown always initialises to a known empty-string value.

Test plan

  • Existing 121 tests continue to pass
  • New test: concurrent _renderEditor() calls produce exactly one ha-form in the shadow DOM
  • New test: _renderGen increments on each call
  • New tests: provider_instance defaults to '' and is preserved when provided

https://claude.ai/code/session_01S6oCbiMD9Zujr5raNFQGgz

claude added 3 commits April 13, 2026 20:39
When Music Assistant has multiple integrations of the same provider
(e.g. 2–3 Spotify accounts), the card now lets users filter content
to a specific account via a new optional `provider_instance` config.

- card: fetch up to 500 items and filter client-side by
  `provider_mappings` when `provider_instance` is set
- editor: new `_fetchProviders()` method extracts unique providers
  from the library; shows a dropdown only when 2+ providers are
  detected, leaving single-integration setups unchanged
- translations: add `editor_provider_instance` / `provider_all` keys
  to all 6 language files (en, es, fr, de, it, pt)
- readme: document the new optional `provider_instance` option
- tests: 7 new tests covering config default and filtering logic

https://claude.ai/code/session_014ncsT8ZdN8iF2RCTje5Eo2
_renderEditor() was changed to async in PR #8 (provider_instance feature)
but no guard was added against concurrent calls. When called multiple times
before the await resolves, each call would query the same live #form-host
and append its own ha-form, resulting in duplicated config fields in the UI.

Fix with a _renderGen generation counter: each call increments it, and any
call that finds a newer generation has started aborts after the await instead
of appending to the DOM.

Also adds the missing provider_instance: '' default to editor.js setConfig,
aligning it with the card.js defaults so the provider dropdown initialises
with a known empty-string value regardless of stored config.

https://claude.ai/code/session_01S6oCbiMD9Zujr5raNFQGgz
…ching

Two bugs prevented the provider_instance selector from appearing:

1. providers.length > 1 was too strict — the selector was hidden even when
   exactly one provider was detected. Changed to >= 1, so it appears as
   soon as any provider is found.

2. _fetchProviders() cached failed fetches (catch set this._providers = [])
   so any transient error (e.g. HA still loading, network hiccup) would
   permanently suppress the selector for that config key. Fixed by moving
   the cache assignment inside the try block — errors are no longer cached
   and the next _renderEditor() call will retry.

Also added fallback: the selector now shows whenever this._config.provider_instance
is already set (e.g. configured via YAML), even if provider discovery returns
nothing, so users can manage or clear an existing value from the visual editor.

https://claude.ai/code/session_01S6oCbiMD9Zujr5raNFQGgz
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.

2 participants