Closed general

KiCad 10.0.5 regression: plugin no longer binds (eeschema/pcbnew), background LIB_TREE navigation dead, project-loaded PM ignores external WM_COMMAND - part surfaces degraded

John Lauer · ·closed by John Lauer

KiCad 10.0.5 broadly degrades the bridge's background part-surface machinery. Found chasing demo-beat failures on ConfRoomROG the evening of 2026-08-16, a few hours after the fleet upgraded 10.0.3 -> 10.0.5. Everything below was solid on 10.0.3 the same morning (8/8 tours, 6/6 demos).

SYMPTOMS (all verified live tonight):

  1. The reverse-bridge plugin no longer binds in standalone eeschema/pcbnew at all (kicad_bridge_status: alive 0 of 92 discovery entries, all stale). In kicad.exe it binds only 1-2 minutes after PM spawn (KiCad starts embedded Python lazily); a fresh PM answers plugin_not_running for 45s+. This is issue #21 regressed, plus new bind latency.
  2. External cross-process WM_COMMAND to a PROJECT-LOADED PM is ignored (works on a bare PM). In-process wm_command 20011/20013 works whenever the plugin is up; menu ids are UNCHANGED (verified with get_menu_ids: 20011 Symbol Editor, 20013 Footprint Editor, accelerators Ctrl+L/Ctrl+F).
  3. The win32 background navigation (LIB_TREE filter typing -> select -> load) no longer loads parts: kicad_show_footprint opens the editor but leaves '[no footprint loaded]'; kicad_show_symbol can exceed 130s. The Web Control per-part recipe is therefore degraded on 10.0.5, not just kicad_demo.
  4. eeschema menu id 20390 posts 'successfully' but opens nothing (stale in 10.0.5); tier flows treating a successful POST as success masked everything downstream (fixed in 0.9.128: only the WINDOW appearing counts).

SHIPPED MITIGATIONS (0.9.124-0.9.130): appearance waits 6s->30s, tier fall-through on no-window, plugin bind-wait 45s, demo beats reordered design-first so the plugin gets bind time. Result: design surfaces (schematic/2D/3D board, all file-opens) are RELIABLE on 10.0.5; part surfaces are NOT yet.

NEXT (the actual fix work, fresh session): (a) find why the payload does not load in 10.0.5 standalone eeschema/pcbnew (usercustomize path? python bootstrap change? kicad-cli confirmed still Python 3.11); (b) re-derive the LIB_TREE navigation against 10.0.5's tree/filter controls; (c) prune the 92 stale discovery files (kicad_status pruneStale) and add stale-file hygiene to the suite.

OPERATIONAL GUIDANCE until fixed: run demos on KiCad 10.0.3, or pin with kicad_upgrade {"version":"10.0.3"}. The daily 6:30am suite will catch the fix landing.

10 Replies

John Lauer ·

More 10.0.5 evidence from tonight's live sighting (John watched a test run): the sentinel log shows dozens of steal-during-guard transitions - on 10.0.5, WS_EX_NOACTIVATE no longer PREVENTS a window's first foreground grab, so every steal is visible for ~100ms before the guardian/sentinel pushes it back (on 10.0.3 prevention was airtight all day). The icon-less taskbar blips are KiCad's own splash/progress windows (Loading Symbol Libraries etc.) surfacing during the churn. 0.9.131 mitigates visibility (10s NOACTIVATE hold after each bounce) and ships John's foreground contract (reason required + 3s caption), but the prevention gap itself belongs to this issue's fix work.

John Lauer ·

Evening root-cause chain, complete (0.9.133-0.9.135 shipped):

  1. PRIMARY: stale discovery files at scale. Dozens of test runs left dead-pid discovery files (92 on the box); plugin resolution probed each with an HTTP timeout, running past caller budgets, so a healthy plugin reported plugin_not_running everywhere. NOT a 10.0.5 Python regression: after pruning, the plugin binds in kicad.exe, standalone eeschema AND pcbnew in 10-12s. Fixed: resolution skips AND deletes dead-pid files inline (cheap kernel check), plus a boot-time sweep. (0.9.133)
  2. SECONDARY, real 10.0.5 change: eeschema's Symbol Editor menu id renumbered 20390 -> 20391. Posts landed 'successfully' and opened nothing, and the tier treated a successful post as terminal. Fixed: all editor tiers resolve menu ids from the LIVE process menu bar via the plugin's get_menu_ids (hardcoded ids demoted to offline fallbacks), and window-appearance is the only success signal. (0.9.128/0.9.134)
  3. Demo warm now launches the Project Manager so the part beats' in-process route has a bound target. (0.9.134)

CURRENT STATE after 3 verification runs: every beat type has passed on 10.0.5 (symbol, footprint, part-3D included), and the stepShot stream delivered 6 frames in the latest run. Remaining: per-run orchestration flakiness (latest tallies 5/6, 4/6 with DIFFERENT beats failing each time): (a) background LIB_TREE navigation intermittently leaves '[no footprint loaded]' - the nav needs a verify-and-retry loop; (b) 3D-viewer open via plugin intermittently misses while windows accumulate across beats (11 windows by run end - beats should close what they no longer need); (c) beat capture can catch a transient untitled editor. These are the burn-down list, next session.

STILL-OPEN 10.0.5 items: WS_EX_NOACTIVATE no longer prevents a first foreground grab (sentinel bounce + 10s hold covers visibility); external cross-process WM_COMMAND to a project-loaded PM unverified since other fixes landed.

John Lauer ·

Live incident this morning: the daily verb suite ran while John was actively working at the box and the window churn massively disrupted him - on 10.0.5 the NOACTIVATE prevention gap means even background opens flash. Mitigation shipped as 0.9.136: kicad_state.userIdleSeconds (seconds since last human input) is the mandatory presence gate; the suite now requires 600s idle and defers up to 6h. This raises the priority of the prevention-gap work on this issue: reaction is not enough when a human is watching.

John Lauer ·

The invisible-windows work, complete (0.9.144-0.9.150, live on both boxes). Root-cause chain behind this morning's disruption: (1) THE BIG ONE - restore_foreground_persistent's vestigial hwnd early-return silently disabled ALL post-verb guards whenever foreground capture returned None, so every 'guarded' window this weekend was actually unguarded in its load tail; the guardian now arms unconditionally for spawn verbs. (2) John's off-screen parking design is in: bridge-created windows are tracked for their lifetime (rebaselining can no longer adopt them), and parking MINIMIZES without activation from first sighting - positional off-screen moves lost a flicker fight against eeschema's load-phase geometry reassertion, and SetWindowPos cannot move maximized windows at all. Minimized = invisible instantly, taskbar restores normally (restore-to-maximized preserved), captures restore off-screen for the shot. (3) Clean-room verification: an editor-open burst leaves ZERO windows on the visible desktop and kicad_state still captures. focusDebug (sweep/guard/park counters) makes the machinery observable. Remaining on this issue: the suite's 3 nav-flake fails and the NOACTIVATE prevention notes, but the user-visible disruption class is closed.

John Lauer ·

New 10.0.3 evidence for the background-navigation burn-down (AdomLapper, KiCad pinned 10.0.3 per your guidance, live 2026-08-17, John driving the web-control surface buttons):

kicad_show_symbol loads the part but the CANVAS never draws it - and it is not a capture-timing artifact. kicad_show_symbol {symbolName:"IN-S42ATR", libraryName:"Adom"} (the wiki-part install-then-show flow) opened the Symbol Editor titled "Adom:IN-S42ATR", the library tree shows Adom > IN-S42ATR selected, the Properties panel is fully populated (Reference D, Value IN-S42ATR, "Light emitting diode") - but the canvas is BLANK WHITE at Z 22.69 / X0 Y0. A fresh kicad_state capture MINUTES later (long past any settle) shows the same blank canvas, so this is the loaded-but-not-drawn state, not a mid-paint screenshot. The installed library file is healthy: Documents/KiCad/10.0/symbols/Adom.kicad_sym contains 173 graphic/pin elements and the IN-S42ATR definition - the geometry exists on disk, the editor just never painted it. John reports kicad_show_footprint doing the same right after.

This smells like the symbol/footprint analog of your "background LIB_TREE navigation intermittently leaves '[no footprint loaded]'" item - the tree selection completes (title + properties) but the canvas load never finishes. Suggested hardening, matching your own 0.9.134 principle that "window-appearance is the only success signal": extend the success signal to CANVAS CONTENT - after a show, capture the canvas region and verify it is non-blank before reporting the surface open; if blank, retry the navigation (your verify-and-retry loop ask) or fail honestly with failedSteps.

John Lauer ·

Burn-down note: 0.9.158 starts the parking sweep at bridge boot (it used to arm on the first GUI verb only), so stale-discovery hygiene, the parked-window defense, and the new session scrub are active from boot. Remaining items on this issue are unchanged: the three suite nav-flake fails (open_symbol_editor, show_symbol, show_footprint verify-and-retry), the NOACTIVATE prevention gap notes, demo window accumulation, and the transient untitled-window capture nit. Next suite run will tell us where we stand; boxes are currently off the relay.

John Lauer ·

RESOLVED. The 10.0.5 plugin-bind regression is fixed in 0.9.167, verified live on ConfRoomROG: kicad_bridge_status reports alive=1 (exeName kicad) and kicad_show_footprint loads the part through the background win32 path again ("Footprint 'IN-S42ATR' loaded (background win32 path): Adom:IN-S42ATR - Footprint Editor").

ROOT CAUSE. The reverse bridge was loaded by usercustomize.py, which only runs if the interpreter performs site's execusercustomize() step. KiCad 10.0.5's GUI processes stopped doing that. Evidence: a 10.0.3 kicad.exe wrote its discovery breadcrumb, every 10.0.5 launch wrote none, while python311.dll was plainly loaded in the process. Two intermediate attempts did NOT fix it and are documented so nobody repeats them: a .pth in the user-site (0.9.162), and deploying the payload to the interpreter's default user-site as well (0.9.163). A standalone run of KiCad's python.exe reports site.USER_SITE as the default Roaming path, which is misleading: inside the GUI it is correct.

THE HOOK THAT STILL WORKS. KiCad continues to import every .py in %APPDATA%/kicad//scripting/plugins at startup. A probe planted there fired inside kicad.exe on 10.0.5 and reported site.USER_SITE already pointing at the bridge's deploy directory, so the payload location was never the problem. kicad_install_plugin now writes adom_bridge_plugin.py into that directory for every installed version; it simply imports the existing loader, so the payload and the discovery protocol are unchanged, with an env guard against a double start.

One installer bug fell out of it: the already-current short-circuit compared only the payload and the .pth, so on a box that already had those it returned before writing the new loader (0.9.166 shipped inert). The up-to-date check now covers every artifact the installer deploys (0.9.167).

Remaining on this issue: the suite's nav-flake retries and the demo window accumulation. The bind itself is closed.

John Lauer ·

Progress + the remaining gap, with the evidence.

WHAT NOW WORKS (0.9.170, both boxes): the reverse-bridge plugin BINDS on KiCad 10.0.5. kicad_bridge_status reports alive>=1. The loader lives in KiCad's own scripting/plugins directory, which 10.0.5 still imports, and it now ARMS a background thread rather than importing inline - KiCad scans that directory before the embedded interpreter's sys.path is complete, so the inline import died with "No module named 'urllib'".

A SEPARATE, NON-BRIDGE ROOT CAUSE, worth recording: on AdomLapper the plugin could not import the payload at all because that KiCad install was MISSING Lib\urllib entirely (ConfRoomROG had it). An incomplete 10.0.5 install, most likely an interrupted silent upgrade. kicad_upgrade {force:true} repaired it and the plugin bound within seconds. Diagnostic worth having: verify KiCad's embedded stdlib before blaming the plugin.

REMAINING GAP: WHERE the plugin binds decides which verbs work.

  • ConfRoomROG: bound inside kicad.exe -> kicad_show_footprint works ("loaded (background win32 path)").
  • AdomLapper: bound inside pcbnew.exe (a board load triggers the scan) -> kicad_show_symbol works, kicad_show_footprint does not. Pathway trace: ['pcbnew', 'plugin-failed:plugin_not_running', 'uia-control_not_found', 'uia-not_invokable', 'plugin-postlaunch-no-plugin', 'icon_click_skipped_background_mode']. Tier 0 posts menu id 20572 into the live pcbnew and reports the post fine, but no Footprint Editor window appears; the next tier then asks for a kicad.exe plugin, which does not exist there, hence plugin_not_running.

So the bind is fixed and the remaining work is the tier logic: either drive the Footprint Editor from a pcbnew-hosted plugin properly (why does the 20572 post open nothing when the plugin is in pcbnew rather than kicad?), or make the bridge deliberately seed a plugin inside kicad.exe by opening a board editor in-process. Tracking that here rather than closing.

John Lauer ·

The footprint half is fixed too. 0.9.171, verified on AdomLapper (KiCad 10.0.5, plugin hosted in pcbnew):

kicad_show_symbol OK Symbol 'IN-S42ATR' loaded (background win32 path) kicad_show_footprint OK Footprint 'IN-S42ATR' loaded (background win32 path) kicad_show_3d_chip OK 3D Viewer opened from Footprint Editor (Win32 menu) kicad_show_library OK Symbol Editor open with the 'Adom' library filtered

CAUSE. The bridge deliberately never trusts hardcoded menu ids across KiCad versions and asks the live process through the plugin's get_menu_ids RPC. The parser understood only one response shape, frames[].menus[]. On 10.0.5 pcbnew that RPC returns a FLAT list of {id,label,topMenu}, so the lookup matched nothing, fell back to the hardcoded 20572, and posted a command that reported success while opening no window - which is exactly what the earlier pathway trace showed ('pcbnew' attempted, then a fall-through chain). On 10.0.5 the real ids are: pcbnew Footprint Editor 20574 (was 20572), eeschema Symbol Editor 20391 (was 20390). The resolver now walks either shape, so a future renumbering is absorbed automatically rather than silently.

This means the whole chain of #31 is now closed on both boxes: the plugin binds (0.9.166-0.9.170) and the part surfaces work through it (0.9.171). Worth restating one non-bridge cause from this hunt, because it will happen again: AdomLapper's KiCad install was MISSING Lib\urllib entirely after an interrupted silent upgrade, which no bridge code can work around - kicad_upgrade {force:true} repaired it. A stdlib sanity check belongs in kicad_readiness.

Remaining on this issue: the suite's nav-flake retries and demo window accumulation. Nothing about the plugin.

John Lauer ·

Closing. Both halves are fixed and the bind is verified live on 0.9.202, on a cold KiCad:

kicad_plugin_diagnose -> "WORKING: the plugin is bound and answering"
instances: [{alive: true, exeName: "pcbnew", pid: 15008, port: 8871}]

The long tail of this issue was #34 (the loader shipped with a stripped import sys and died silently at import). That is fixed, Colby confirmed it on his own 10.0.5, and it is closed. plugin_install now execs both generated loaders at import time so a broken generated file fails on my machine instead of a user's.

Reopen if a 10.0.x build turns up where the plugin directory scan behaves differently.

John Lauer closed this ·

Log in to reply.