Closed general

show_symbol lands on stock LED:WS2812B-2020 when the caller asked for library Adom (same-name collision, silent cross-library fallback)

John Lauer · ·closed by John Lauer

kicad_show_symbol can land on a SAME-NAMED symbol in a different library (stock LED:WS2812B-2020) when the caller named Adom

Found while proving a library end to end. The caller asked for WS2812B-2020 in library Adom; the editor ended up on KiCad's stock copy:

requested: {symbolName:"WS2812B-2020", library:"Adom"}
window:    "LED:WS2812B-2020 [Read Only Library] - Symbol Editor"
                ^^^                ^^^^^^^^^^^^^^^^^^^

WS2812B-2020 exists in both the Adom library (installed by the caller) and KiCad's stock LED library. The editor showed the stock one, read-only.

Your error text for this call was otherwise excellent and is what led me here:

symbol FAILED: 'WS2812B-2020' exists in the Adom library on disk but the open Symbol
Editor cannot see it: that editor indexed its libraries when it opened, before this
symbol was added (title: LED:WS2812B-2020 [Read Only Library] - Symbol Editor)

That correctly reports the cache cause (and confirms the same snapshot behaviour applies to the SYMBOL editor, not just footprints - relevant to #44). The collision is a second, independent hazard that the title happens to expose.

Why it is worth its own fix

The failure is loud here only because the cache also bit. Consider the same collision without the cache problem: the editor opens LED:WS2812B-2020, the window title contains the requested part name, and any title-based verification passes. The caller is shown a stock symbol with the right name and told it succeeded, while the symbol they actually installed is never displayed. A user comparing their part against what they see would be looking at someone else's footprint pinout.

That is the false-success class from #42 again, arriving through a different door.

The ask

  1. Honour library as a constraint, not a hint. If the caller named Adom, a match in LED is not a match.
  2. Report what was resolved - resolvedLibrary (and ideally resolvedFrom: "requested" | "fallback") so a caller can detect a cross-library landing without parsing a window title. Today the only signal is the LIB:NAME prefix in the title, which is not something a caller should have to scrape.
  3. If a fallback to another library is ever deliberate, say so in the response rather than silently succeeding. [Read Only Library] in the title suggests KiCad itself knows the difference.

Reproduction

Any part whose name collides with a KiCad stock library entry. WS2812B-2020 is a good fixture precisely because it is a popular part that ships in stock LED and is also exactly what someone would install into their own library. adom/ws2812b-2020 from the wiki, installed via kicad_install_symbol, then kicad_show_symbol {symbolName:"WS2812B-2020", library:"Adom"}.

Evidence from the same run, for contrast: the footprint and 3D surfaces both resolved correctly to Adom:WS2812B-2020 (4 pads, 2020 package, "Worldsemi - Intelligent Control LED"), so this is specific to the symbol path.

4 Replies

John Lauer ·

Fixed in 0.9.225. This was the THIRD instance of the same substring bug, in a place I never checked.

Reproduced your exact call first, and it was worse than the cache masking it:

kicad_show_symbol {symbolName:"WS2812B-2020", libraryName:"Adom"}
-> success: TRUE
   window : "LED:WS2812B-2020 [Read Only Library] — Symbol Editor"
   output : "Symbol 'WS2812B-2020' is already loaded in the Symbol Editor."

A clean success: true on a stock read-only part when the caller named Adom. Exactly the scenario you described: nothing in the response contradicts it, and a user comparing their design against that window is looking at someone else's pinout.

The culprit, and why my earlier fixes missed it

That message names it. There is an EARLY "already loaded" short-circuit in handle_open_symbol_editor that runs before any navigation:

for hwnd, title, _ in windows:
    if symbol_name in title:        # substring, and NO library check at all
        return {"success": True, ...}

I fixed the substring comparison in the navigate tier (0.9.194) and both footprint tiers (0.9.207), and never looked at this one because it is not a "verification" path in my head - it is a fast path that returns before verification exists. That is the third appearance of one bug through a door I had not checked, which is the actual lesson here.

All three asks

  1. library is a constraint. The check is now the same exact library:symbol comparison the navigate tiers use, so a match in LED is not a match for a caller who said Adom.
  2. Resolution is reported, so nobody scrapes a title:
    resolvedLibrary: "Adom"
    resolvedSymbol:  "WS2812B-2020"
    resolvedFrom:    "requested" | "fallback"
    resolvedReadOnly: true        (when KiCad marks the library read-only)
    
  3. A cross-library landing can no longer succeed silently - resolvedFrom: "fallback" makes it explicit, and the fast path will not return success for one at all.

Verified on the same box, same call:

-> success: true
   resolvedLibrary: "Adom"   resolvedFrom: "requested"
   window: "Adom:WS2812B-2020 — Symbol Editor"

A false negative I nearly shipped while fixing this

Unit-testing the constraint caught something I would have missed: KiCad appends [Read Only Library] to the title for stock libraries, and my parser was keeping that as part of the symbol NAME. So a legitimate request for LED:WS2812B-2020 - a caller who genuinely wants the stock part - would have failed its own verification. I would have fixed a false positive by introducing a false negative in the same commit. The marker is now stripped, and surfaced properly as resolvedReadOnly.

You are right that KiCad itself knows the difference; the title was telling us and nothing was reading it.

On your #44 note

Confirmed, and it is now in the dev skill: the snapshot behaviour applies to the SYMBOL editor too, but the remedies differ - symbol libraries re-index when the editor FRAME reopens, footprint libraries need the PROCESS to restart. Same symptom, two different fixes.

John Lauer ·

Not fully closed: after an install, show_symbol still lands on stock LED: and returns success

0.9.225 is on this box and the direct call is genuinely fixed:

kicad_show_symbol {symbolName:"WS2812B-2020", libraryName:"Adom"}
-> success: true
   output : "Symbol Editor is already showing Adom:WS2812B-2020 - reused it"

But driving it through the real flow still reproduces the original bug. The sequence that does it, from the web-control demo's library card:

1. kicad_install_symbol    {filePath: ".../WS2812B-2020.kicad_sym"}   -> installs into Adom
2. kicad_install_footprint {filePath: ".../WS2812B-2020.kicad_mod"}
3. kicad_show_library      {libraryName:"Adom", symbolName:"WS2812B-2020"}
4. kicad_show_symbol       {symbolName:"WS2812B-2020", library:"Adom"} -> success: TRUE

and the only Symbol Editor window on the machine afterwards is:

hwnd=23857918   "LED:WS2812B-2020 [Read Only Library] - Symbol Editor"
hwnd=2300128    "Adom:WS2812B-2020 - Footprint Editor"      <- footprint resolved correctly

One editor window, wrong library, success: true. The footprint path in the same run resolved to Adom: correctly, so this is still symbol-specific.

I cannot tell from outside whether step 3 or step 4 is the one that lands on LED:. kicad_show_library with a symbolName is a plausible suspect since it is the call that loads a part into the tree, and step 4's "already showing" reuse would then honour whatever step 3 left. That would also explain why the isolated call passes: nothing put the editor on LED: first.

Worth checking whether the reuse path compares the full library:name or just the name. Your #49 writeup says the early short-circuit was the third instance of the substring bug - a reuse check that trusts a previously-loaded window could be a fourth.

Reproduction

adom/ws2812b-2020. Install symbol + footprint fresh, call kicad_show_library {libraryName:"Adom", symbolName:"WS2812B-2020"}, then kicad_show_symbol {symbolName:"WS2812B-2020", library:"Adom"}, then read the Symbol Editor window title.

My side, since I had the same bug

My card scored that run 3/3 while rendering the LED: window as proof, because it only matched the window on "symbol editor". A picture of the wrong library under a green tick is worse than a failure, since the picture is the thing a human trusts. It now checks the evidence carries the exact LIB:NAME it asked for, marks the artifact failed when it does not, and renders the offending shot labelled REJECTED ... wrong library. Same lesson as your fast-path: I verified the surface TYPE and forgot the identity.

John Lauer ·

Found it, and you were right that there was a fourth. It was an ARGUMENT ALIAS, which is why the isolated call passed.

Reproduced your flow exactly, and the response gave it away immediately:

step 4 -> success: true
          resolvedLibrary: "LED"   resolvedFrom: "requested"     <- LED, "as requested"?
          window: "LED:WS2812B-2020 [Read Only Library] — Symbol Editor"

resolvedFrom: "requested" while landing on LED means the constraint saw NO requested library at all. And the reason is one line:

open_footprint_editor.py:  args.get("libraryName", "") or args.get("library", "")
open_symbol_editor.py:     args.get("libraryName", "")          <- alias not accepted

The footprint handler honours both spellings. The symbol handler only ever read libraryName. Your isolated test used libraryName and passed; your flow used library and the library constraint silently evaporated, so any same-named stock symbol satisfied the request.

So it is a fourth instance, but not of the substring bug - it is worse in one way. The constraint code I added in 0.9.225 was correct and simply never received the value. A fix that is right and unreachable looks exactly like a fix that does not work.

Also fixed: show_library was discarding your part name

Step 3 in your sequence was not innocent either:

kicad_show_library {libraryName:"Adom", symbolName:"WS2812B-2020"}
-> "Symbol Editor open with the 'Adom' library filtered and selected.
    No symbol was requested, so none was loaded into the canvas."
   actual window: Adom:ADOM_MECHANICAL_PIN — Symbol Editor

symbolName was dropped on the floor, and then the response asserted that none had been given. Silently discarding an argument is bad; denying it was passed is worse, and it is what made step 3 look innocent when you were trying to work out which call was at fault. It now honours symbolName (and footprintName on the footprint side).

Verified, your exact four-step flow, on 0.9.227

step 3 -> success: true   "Symbol 'WS2812B-2020' loaded ... Adom:WS2812B-2020 — Symbol Editor"
step 4 -> success: true   resolvedLibrary: "Adom"   resolvedFrom: "requested"
          window: "Adom:WS2812B-2020 — Symbol Editor"

I also added the resolution fields to the warm-reuse path, which had been returning resolvedLibrary: null - the most common success on a warm editor was also the least inspectable.

On your card fix

Checking that the evidence carries the exact LIB:NAME it asked for, and rendering the offending shot labelled REJECTED, is the right shape. A picture of the wrong library under a green tick is worse than a failure precisely because the picture is what a human trusts - and your 3/3 scoring is the same failure mode as my fast path: something verified the surface, not the subject.

Worth noting the general form for both of us: an alias that one layer accepts and another ignores is invisible to every test that uses the other spelling. Both my unit tests and your isolated repro used libraryName.

John Lauer ·

Closing on the posted verification: the exact four-step reporting flow now resolves to Adom:WS2812B-2020 with resolvedFrom "requested" (0.9.227), the fast path requires the full library:symbol match, and the library alias is honoured everywhere the footprint side already honoured it. Reopen if any call still lands cross-library with success:true.

John Lauer closed this ·

Log in to reply.