Skip to content

fix: a pad reporting activeProfileId -1 took the app down on start - #10

Closed
Cipher-85 wants to merge 1 commit into
schacon:mainfrom
Cipher-85:fix/negative-active-profile-id
Closed

Cipher-85 wants to merge 1 commit into
schacon:mainfrom
Cipher-85:fix/negative-active-profile-id

Conversation

@Cipher-85

Copy link
Copy Markdown

The crash

A Creator Micro 2 (product id 0x8298, over Bluetooth LE) reports activeProfileId: -1 in its keymap.json. KeymapManager.activeLayerKeymap did

let profile = index < profiles.count ? profiles[index] : profiles.first

which only guards the upper bound, so -1 passes straight into the subscript and Swift traps:

Swift runtime failure: Index out of range
specialized static KeymapManager.activeLayerKeymap(_:)   KeymapManager.swift:89
specialized static KeymapManager.isAgentKeymapApplied(_:) KeymapManager.swift:111
specialized static KeymapManager.apply(_:)               KeymapManager.swift:209
BridgeController.ensureKeymap()                          BridgeController.swift:225
BridgeController.openDevice()                            BridgeController.swift:219
BridgeController.start()                                 BridgeController.swift:138

The bridge starts from the .task on the menu panel, so this is the first click on the menu-bar icon, every launch, for anyone whose pad reports a negative id. The fixture and docs/hacking.md both assume 0, which is presumably why it never showed up. The same one-sided check was in activeLayerLayout, withAgentKeymap and PadEmulator.refreshBinding.

The fix

One activeProfileIndex(_:among:) resolves the index, trusting activeProfileId only when it is a real index and falling back to the first profile otherwise - which is what an oversized id already did. The three keymap lookups and the emulator go through it. The pad's own activeProfileId value is left untouched on write; only the lookup is clamped.

Two tests feed -1 and 99 through activeLayerKeymap, activeLayerLayout, isAgentKeymapApplied and withAgentKeymap.

Verified on the pad that triggered it: the panel opens and the bridge runs where it used to trap.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EaYv7dSTLSNUJdZTsV3Fwv

A Creator Micro 2 over Bluetooth LE reports `activeProfileId: -1` in its
keymap.json. The profile lookup only checked the upper bound, so -1 went
straight into the subscript and trapped with "Index out of range" the moment
the bridge started - which is the first click on the menu-bar icon, every
time.

Resolve the index in one place, falling back to the first profile for any id
outside the range (what an oversized id already did), and use it from the
three keymap lookups and the emulator. Two tests feed -1 and an oversized id
through every path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EaYv7dSTLSNUJdZTsV3Fwv
@Cipher-85 Cipher-85 closed this Sep 4, 2026
@Cipher-85
Cipher-85 deleted the fix/negative-active-profile-id branch September 4, 2026 14:38
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.

1 participant