Skip to content

fix: create pcb_ports for url-loaded footprints with duplicated pad numbers - #3435

Open
marcos452652258-gif wants to merge 2 commits into
tscircuit:mainfrom
marcos452652258-gif:fix/kicad-url-loaded-footprint-missing-pcb-ports
Open

fix: create pcb_ports for url-loaded footprints with duplicated pad numbers#3435
marcos452652258-gif wants to merge 2 commits into
tscircuit:mainfrom
marcos452652258-gif:fix/kicad-url-loaded-footprint-missing-pcb-ports

Conversation

@marcos452652258-gif

Copy link
Copy Markdown

Summary

KiCad footprints loaded through footprintFileParserMap (URL/blob/static asset) were added as bare primitives without a Footprint wrapper, and existing ports were never re-marked for re-render after the async load finished. Components using such footprints ended up with zero pcb_port elements, making every pin unroutable.

Repro before this patch (kicad:Battery/BatteryHolder_Keystone_3002_1x2032, converted with KicadFootprintToCircuitJsonConverter): 3 pcb_smtpad, 2 source_port, 0 pcb_port.

Root cause

The library-footprint load path (loadFootprintLibraryResultOrThrow) wraps loaded components in a Footprint({ src }) child and re-marks "PcbPortRender" on existing ports after adding them. The file-parser path did neither:

  1. Without the wrapper, getPortsFromFootprint() can never read port hints from loaded children once available.
  2. Without re-marking PcbPortRender, ports whose initial render happened before the async load kept zero PCB matches and Port_doInitialPcbPortRender bails out early (matchedComponents.length === 0), so no pcb_port is ever inserted.

Additionally, footprints like the Keystone 3002 battery holder have two physical positive pads sharing KiCad pad number 1. The library path already handles this via connected-cluster analysis producing a primary port plus pin1_internal_N ports — the URL path now gets the same treatment.

Changes

  • NormalComponent_doInitialPcbFootprintStringRender.ts: wrap file-parser footprint components in a Footprint({ src }) wrapper (same as the library path) and re-mark PcbPortRender on existing ports after the async load.
  • Regression test using the real KiCad 10 footprint fixture.

Verification

(pass) kicad battery holder positive pads get routable pcb_ports
7 expect() calls

After the patch: 3 source_port, 3 pcb_port (POS + pin1_internal + NEG), internal connection recorded, and <trace from=".BT1 > .POS" to=".BT1 > .NEG" /> routes successfully.

Fixes tscircuit/tscircuit#4444

…umbers

KiCad footprints loaded via URL/blob (footprintFileParserMap) were added
as bare primitives without a Footprint wrapper, and existing ports were
never re-rendered after the async load. Components using such footprints
ended up with zero pcb_ports, making every pin unroutable.

Two changes, mirroring the library-footprint load path:

1. Wrap file-parser footprint components in a Footprint child (with src)
   so getPortsFromFootprint reads port hints from loaded children.
2. Re-mark PcbPortRender on existing Ports after the load completes.

With both, duplicated-numbered physical pads (e.g. the two positive
terminals of BatteryHolder_Keystone_3002 sharing pad number 1) resolve
into a primary port plus internally-connected pin1_internal_N ports with
their own pcb_ports, matching the library-ref behavior.

Adds a regression test using the real KiCad 10 battery holder footprint.

Fixes tscircuit/tscircuit#4444
@vercel

vercel Bot commented Aug 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tscircuit-core-benchmarks Ready Ready Preview Aug 25, 2026 9:38pm

Request Review

When a footprint loads asynchronously (URL/blob via footprintFileParserMap),
source traces could keep referencing port ids from before the load recreated
the ports, and SourceDesignRuleChecks never re-ran. Ports that were actually
connected by a trace kept stale source_pin_missing_trace_warning entries.

- Re-mark SourceTraceRender on subcircuit traces after the file-parser
  footprint load so traces resolve against live port ids
- Add updateSourceDesignRuleChecks to NormalComponent so the marked phase
  actually re-runs; the check now clears its own previous warnings first,
  making re-runs idempotent

Fixes tscircuit/tscircuit#4442
@marcos452652258-gif

Copy link
Copy Markdown
Author

Added a second commit fixing the related stale-warning issue #4442 (same async-load root): after the file-parser footprint load, subcircuit traces re-resolve against the live port ids and SourceDesignRuleChecks re-runs idempotently, so ports actually connected by a trace no longer keep stale source_pin_missing_trace_warning entries. Regression tests cover both the false-positive suppression and that legitimate warnings for unconnected pins still fire.

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.

KiCad Keystone 3002 battery holder: positive pads get no pcb_port

1 participant