KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge — multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
Amendment (required): each verb needs hint/related/pitfalls, and EVERY kicad_call must return a rich `_hint`
⚠️ CORRECTION (see the pinned reply below): this original root cause is WRONG. It was NOT a version skew. The real cause was a missing Chrome native-messaging host registration (
HKCU\...\NativeMessagingHosts\inc.adom.native_browserabsent), and the 0.1.2→0.1.3 diff touches only a file-upload feature, not the connection path. The accurate diagnosis, fix, and revised asks are in the correction reply. Leaving the text below for history.
Summary
On a machine that was working as recently as 2026-07-20, the native-browser extension stopped connecting after Adom Desktop auto-synced the bridge forward to 0.1.49. The service worker is installed and enabled but never establishes the native-messaging channel. The only user-visible signal is Chrome's cryptic "Unchecked runtime.lastError: Native host has exited." (screenshot below).
Root cause is a version skew that fails silently: this machine runs a stale 0.1.2 extension/host against bridge 0.1.49, and the bridge's own bridge.json advertises expectedExtensionVersion: 0.1.3 while the actually-shipping extension is 0.4.14. So even the built-in skew check is comparing against the wrong number and can never tell the user to update. On top of that, the host exits with code 0 (no message) and stale singleton PID files appear to block a fresh host.
This is bridge-author territory (the native-messaging host code, bridge.json, and the nbrowser_ diagnostics), so filing here rather than against adom-desktop.
Environment
- Machine: adom_drew2 (Windows), user
drew - Chrome: 150.0.7871.129, profile
chrome:[email protected](Default) - Adom Desktop: recent self-update around 2026-07-22 (bridge log shows a rotated bridge token:
AD rejected our bridge token (403) ... AD likely self-updated and rotated it) - Bridge installed: native-browser 0.1.49 (
.bridge-version= 0.1.49,bridge.jsonversion = 0.1.49).bridge_check_updatesreports current 0.1.49 = latest,updateAvailable: false. - Extension/host installed (unpacked):
C:\Users\drew\adom-browser-extension\extension\manifest.json→ name "Adom for Chrome & Edge", version 0.1.2, MV3. The host code (host\native-host.js,native-host.bat,host-manifest.json) is from the same 0.1.x checkout. - Latest on the wiki: extension line is at 0.4.14 (published 2026-07-23), bridge line at 0.1.49 (2026-07-22).
Symptom
chrome://extensions shows the Adom card Enabled with an Errors button. The error detail reads:
Unchecked runtime.lastError: Native host has exited.
nbrowser_status → native browser extension not connected. nbrowser_wake_profile {profile:"chrome:[email protected]"} → woke:false with the diagnosis "installed AND enabled ... but its service worker has not dialed the bridge." The bridge log never records a host connection after the reload (no hello: profile ... registered line).
Repro
- Install/enable the 0.1.2 extension unpacked in a Chrome profile (host code from the same checkout).
- Let Adom Desktop auto-sync the bridge forward to 0.1.49 (or
refresh_bridges native-browser). - Register the native host and reload the extension.
- Observe:
chrome://extensions→ Adom card → Errors → "Native host has exited";nbrowser_statusstays "not connected"; bridge log shows no hosthello.
Root-cause analysis
The 0.1.2 host is protocol-incompatible with the 0.1.49 bridge: the host process launches, fails to complete the handshake/singleton, and calls process.exit(0), which Chrome surfaces as "Native host has exited." Three compounding, bridge-side defects turn a routine version skew into an hour-long dead end:
bridge.jsonexpectedExtensionVersionis stale. It reads0.1.3, but the shipping extension is0.4.14. Any skew detection that compares the connected extension version against this field is comparing against the wrong baseline, so it can never say "you're on 0.1.2, update to 0.4.14." (The page publishing two interleaved version lines — bridge 0.1.x and extension 0.4.x — is itself a confusion worth resolving or documenting.)The host exits silently on skew.
native-host.jshas severalprocess.exit(0)paths with no user-visible reason:acquireSingleton(line ~63) exits if another host holds the profile's singleton lock.- the reconnect policy gives up after max backoff (lines ~311/315) and exits. None of these emit a "your extension is out of date, update to X" signal; the user only ever sees Chrome's generic "Native host has exited."
Stale singleton lock not reclaimed. The bridge dir had two stale lock files —
host.nohello-67004.pidand[email protected]— referencing dead PIDs. A fresh host appears to exit rather than steal a dead-PID lock. (Deleting them + restarting the bridge did not by itself restore the connection, so skew is the primary cause, but the stale lock is a second foot-gun.)
Timeline supporting "regression, not fresh-install": bridge-debug.log shows successful hello: profile chrome:[email protected] registered on 2026-07-17 and 2026-07-20. Bridge releases 0.1.42–0.1.49 were published 2026-07-22. So the bridge moved forward under a host that stayed at 0.1.2.
Possibly-related older crash (may already be fixed in 0.1.49): the 2026-07-17 debug log has unhandledRejection: TypeError: (payload.closed || []).map is not a function at onHostFrame (server.js:1636:91) from an earlier bridge. Worth confirming the payload.closed guard exists on all onHostFrame paths in 0.1.49.
What I already fixed on this machine (not the bug)
The Chrome native-messaging host key was missing (removed at some point, likely during an AD update). I re-created HKCU\Software\Google\Chrome\NativeMessagingHosts\inc.adom.native_browser → ...\host\host-manifest.json. That changed the error from "native host not found" to "native host has exited", isolating the remaining failure to the host-exit / skew issue above.
Suggested fixes (asks)
- Bump
bridge.jsonexpectedExtensionVersionto the real current extension (0.4.14), and keep it in lockstep on future extension releases. Resolve or document the two-version-line scheme (bridge 0.1.x vs extension 0.4.x). - Fail loud on skew. When the connected host/extension is older than the bridge expects, surface a clear "extension out of date, update to
<version>" through the bridge and the nbrowser_ verbs, instead ofexit(0)→ "Native host has exited." - Self-heal stale singleton locks. If
host.*.pidpoints at a dead PID, reclaim the lock rather than exiting. - Surface diagnosis in verbs.
nbrowser_readiness/nbrowser_wake_profileshould reportextensionStale(installed vs expected) and the host-exit reason, so this is one call rather than manual spelunking throughbridge-debug.log,host.json, andchrome://extensionserrors. - Confirm the
(payload.closed || []).mapguard is present on all onHostFrame paths in 0.1.49.
Attached
chrome://extensions error detail showing "Native host has exited" for the Adom extension.