DESCRIBE THE BUG
The UF2 runner rejects --dev-id with a fatal error before any flashing occurs, even though the runner never uses a device serial number.
The nRF Connect VS Code extension unconditionally appends -i <serial> to west flash whenever it detects a connected Nordic device, regardless of which runner is selected. Because UF2BinaryRunner.capabilities() did not declare dev_id=True, the base-class guard in ZephyrBinaryRunner.create() aborts immediately with a fatal error.
STEPS TO REPRODUCE
- Use a board with a UF2 bootloader and no on-board J-Link (tested: Seeed XIAO nRF52840, UF2 drive mounts at G:).
- Add
set(BOARD_FLASH_RUNNER uf2) before find_package(Zephyr ...) in CMakeLists.txt.
- Open the project in VS Code with the nRF Connect SDK extension.
- Put the board in UF2 bootloader mode (double-tap reset, drive appears).
- Click Flash — the extension calls:
west flash -d build -i F3ADA8E6C5AA9120
→ west aborts immediately. Nothing is copied to the drive.
RELEVANT LOG OUTPUT
west flash -d c:\mynRF\blinky\build -i F3ADA8E6C5AA9120
FATAL ERROR: uf2 doesn't support --dev-id option
IMPACT
Major – the UF2 runner is completely unusable from any IDE or tool that passes --dev-id. The only workaround is manually copying the .uf2 file in Explorer.
ENVIRONMENT
- OS: Windows 11
- Board: Seeed XIAO nRF52840 (UF2 bootloader, no on-board J-Link)
- Zephyr: reproduced on v3.7 (nRF Connect SDK v3.2.4), present in main
- West: bundled with nRF Connect SDK toolchain
- IDE: VS Code + nRF Connect SDK extension
ADDITIONAL CONTEXT
UF2BinaryRunner.capabilities() returns RunnerCaps(commands={'flash'}) without dev_id=True. The base-class guard in
ZephyrBinaryRunner.create() (core.py line 676) rejects any runner that receives --dev-id without declaring it:
if args.dev_id and not caps.dev_id:
_missing_cap(cls, '--dev-id')
UF2 flashing is connectionless — the runner identifies the target drive via INFO_UF2.TXT using --board-id. do_create() reads only args.board_id; args.dev_id has no meaning for this transport.
Fix — declare dev_id=True and emit a warning so users know the value is accepted but has no effect on target selection:
@classmethod
def capabilities(cls):
- return RunnerCaps(commands={'flash'})
+ return RunnerCaps(commands={'flash'}, dev_id=True)
@classmethod
def do_create(cls, cfg, args):
- return UF2BinaryRunner(cfg, board_id=args.board_id)
+ return UF2BinaryRunner(cfg, board_id=args.board_id, dev_id=args.dev_id)
def do_run(self, command, **kwargs):
+ if self.dev_id:
+ self.logger.warning('--dev-id %s is not used by the UF2 runner '
+ 'and will be ignored', self.dev_id)
DESCRIBE THE BUG
The UF2 runner rejects
--dev-idwith a fatal error before any flashing occurs, even though the runner never uses a device serial number.The nRF Connect VS Code extension unconditionally appends
-i <serial>towest flashwhenever it detects a connected Nordic device, regardless of which runner is selected. BecauseUF2BinaryRunner.capabilities()did not declaredev_id=True, the base-class guard inZephyrBinaryRunner.create()aborts immediately with a fatal error.STEPS TO REPRODUCE
set(BOARD_FLASH_RUNNER uf2)beforefind_package(Zephyr ...)inCMakeLists.txt.west flash -d build -i F3ADA8E6C5AA9120→ west aborts immediately. Nothing is copied to the drive.
RELEVANT LOG OUTPUT
IMPACT
Major – the UF2 runner is completely unusable from any IDE or tool that passes
--dev-id. The only workaround is manually copying the.uf2file in Explorer.ENVIRONMENT
ADDITIONAL CONTEXT
UF2BinaryRunner.capabilities()returnsRunnerCaps(commands={'flash'})withoutdev_id=True. The base-class guard inZephyrBinaryRunner.create()(core.pyline 676) rejects any runner that receives--dev-idwithout declaring it:UF2 flashing is connectionless — the runner identifies the target drive via
INFO_UF2.TXTusing--board-id.do_create()reads onlyargs.board_id;args.dev_idhas no meaning for this transport.Fix — declare
dev_id=Trueand emit a warning so users know the value is accepted but has no effect on target selection:@classmethod def capabilities(cls): - return RunnerCaps(commands={'flash'}) + return RunnerCaps(commands={'flash'}, dev_id=True) @classmethod def do_create(cls, cfg, args): - return UF2BinaryRunner(cfg, board_id=args.board_id) + return UF2BinaryRunner(cfg, board_id=args.board_id, dev_id=args.dev_id) def do_run(self, command, **kwargs): + if self.dev_id: + self.logger.warning('--dev-id %s is not used by the UF2 runner ' + 'and will be ignored', self.dev_id)