XKNX / XKNX/xknxtoolkit

[Detail Bug] Configure panel shows stale programming checklist after switching devices

Open
#103 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
4
Forks
0
Avg merge
15h 38m
Merged PRs (30d)
37

Description

Detail Bug Report

https://app.detail.dev/org_62aa40f5-2c23-4914-a665-3bb2068af20e/bugs/bug_63e4ce9a-bebd-4676-9b7a-e94ad7add731

Introduced in #35 by @kewde on Sep 11, 2026

Summary

  • Context: ProgramSection (in apps/knx-gui/src/knx_gui/plugins/project/ui/components/program_section.py) renders the "Program Device" subsection of the Configure panel; it is a long-lived instance held by ConfigurePanel and accumulates post-program status (_status, _checklist) baked-in with the active device's individual_address at _start time.
  • Bug: When the user switches the selected device via the ##device_select combo at the top of the Configure panel while a program operation is running, succeeded, or errored, ConfigurePanel resets only its own text buffers and never resets ProgramSection, so the next frame renders the new device's name next to the old device's stale checklist items.
  • Actual vs. expected: The panel header correctly reads Program Device: <NewDevice> (it tracks the live device argument), but the checklist row below it still claims [+] Write Individual Address <OldDevice.individual_address> — the only per-device label, baked in at _start time. The other checklist rows are static strings (Waiting for a device in programming mode / Addressing device by serial number / Group Addresses / Parameters) and do not go stale. The section should either re-render with the new device's programming state (idle/find_device) or be reset to idle on device switch.
  • Impact: The defect is the mismatch between an accurate header and one stale row — the user sees Program Device: DeviceB directly above [+] Write Individual Address 1.1.4 (DeviceA's address), eroding trust in the panel's feedback. Most concerning when switching mid-program: the in-flight bus operation is still writing DeviceA's IA while the panel presents the result under DeviceB's name once the Future resolves.

Code with Bug

In apps/knx-gui/src/knx_gui/plugins/project/ui/configure.py, the device-change branch resets ConfigurePanel's own buffers but never touches ProgramSection:

if self._buffer_device_id != device.node_id:
    self._name_buffer = device.name
    self._sync_address_buffers(device.individual_address)
    self._serial_buffer = ""
    self._buffer_device_id = device.node_id   # <-- BUG 🔴 no reset of self._program_section state/checklist

In apps/knx-gui/src/knx_gui/plugins/project/ui/components/program_section.py, stale checklist labels are rendered under the newly selected device name:

def _render_status(self, device: Device) -> None:
    imgui.text(S.BTN_PROGRAM_DEVICE + f": {device.name}")   # NEW device name
    imgui.spacing()
    for label, item_status in self._checklist:              # STALE labels (old IA)  <-- BUG 🔴 stale checklist rendered under new device's name
        self._render_checklist_item(label, item_status)

The per-device checklist label is captured at request time and never re-evaluated:

if request.program_individual_address:
    self._ia_checklist_index = len(self._checklist)
    self._checklist.append(
        (
            S.PROGRAM_CHECKLIST_WRITE_IA.format(
                address=device.individual_address           # baked-in; not refreshed on device switch
            ),
            "current",
        )
    )

Explanation

ConfigurePanel keeps a single ProgramSection instance for the lifetime of the panel. On device switch, ConfigurePanel updates its own buffers (name/address/serial) but does not reset ProgramSection’s state (_status, _checklist). ProgramSection._render_status() then uses the newly selected device for the header while rendering the previously constructed _checklist, which contains one device-specific label (Write Individual Address {address}) baked in at _start() time.

This is reproducible after a completed program (success/error), and also during an in-flight program because the device combo is always enabled; switching devices mid-program can lead to the old Future resolving later and updating ProgramSection while the panel is showing a different selected device.

Recommended Fix

Add a reset() method on ProgramSection to return it to its idle state (clear _checklist, _status, etc.) and call it from the ConfigurePanel device-change branch.

Additionally, guard against stale Future callbacks when switching devices mid-program by invalidating or ignoring callbacks from earlier starts (e.g., a generation token recorded at _start() and checked in _handle_future_done()).

History

This bug was introduced in commit 177a196. The commit added the ProgramSection sub-component to the Configure panel and, in the same diff, extended the existing device-change buffer-reset branch to clear the new _serial_buffer it introduced — but did not add any corresponding reset for the new stateful self._program_section, so the device-switch path that already reset ConfigurePanel's own buffers left ProgramSection's _status/_checklist intact. The commit is the true origin (not a move/rename): ProgramSection did not exist before this commit, and the only later commit touching configure.py (753ce7a, moving the Preview Memory button) does not touch the device-change branch. The author appears to have noticed the per-session _serial_buffer needed clearing on device switch but overlooked that the new sub-component held its own accumulated state.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/knx-gui/src/knx_gui/plugins/project/ui/configure.py at the device-change branch, then inspect ProgramSection in apps/knx-gui/src/knx_gui/plugins/project/ui/components/program_section.py, including _start(), _render_status(), and _handle_future_done(). Done means switching devices clears the old checklist and status, and an earlier operation cannot update the newly selected device's panel.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
75/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.