The improved error logging from the last fix immediately paid off — real
esptool output on the next attempt showed two distinct bugs:
1. Debian's esptool package (4.7.0+dfsg-0.1) ships without the precompiled
"stub flasher" blobs (stripped for DFSG compliance), so the default
stub-loader flash mode fails immediately: FileNotFoundError: ... No such
file or directory: '.../stub_flasher_32s3.json'. Fixed with --no-stub,
which talks directly to the ROM bootloader instead — the standard
workaround for this exact Debian packaging gap.
2. The fallback-baud retry appended `--baud 115200` AFTER the subcommand
token (erase_flash/write_flash), but esptool requires global flags
before the subcommand — every retry failed with "esptool: error:
unrecognized arguments: --baud 115200", so the retry logic added
earlier never actually got a chance to run. esptool_with_retry now
builds global args (--chip/--port/--baud/--no-stub) and subcommand args
separately and always concatenates them in the right order, instead of
relying on call-site ordering of a single flat arg list.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>