ESP32/Setup and uploading/06. When uploads fail
Your chip
Your language
Setup and uploading · 06 of 81

When uploads fail

The port vanished, esptool prints dots and gives up, or the board uploads once and never again. All three have the same small set of causes, and none of them are your code.

/esp32/when-uploads-fail · arduino · S3

The one rule

The chip reads GPIO 0 at the instant reset is released. Low means wait for esptool; high means run the sketch. Everything on this page is that rule being satisfied, or not.

The board's own reset circuit
download mode
IO0 at the edge
LOW
Chip boots into
download mode
IO0 was low when EN went high, so the chip is waiting for esptool. That is the entire trick. The IDE does it for you: two transistors on the board turn the USB chip's DTR and RTS lines into exactly this pattern, which is why you normally never touch a button.

Reading the error

  • No serial data received — the chip never entered download mode. Button sequence, or a bad cable.
  • Wrong boot mode detected — it entered, then left. Something is pulling a strapping pin.
  • The port is not in the list at all — the operating system never saw a USB device. Cable, driver, or a native-USB board whose sketch has crashed.
  • It uploads, then nothing on the Serial Monitor — that is not an upload failure. Check the baud rate.

When nothing works

Erase the flash. A half-written partition table or a failed OTA leaves the board boot-looping in a way that also blocks uploads, and esptool.py erase_flash clears it in ten seconds. You lose stored settings and uploaded files, which is exactly what you want at this point.

On your S3
ChipXtensa LX7 · 2 × 240 MHz
Board settingESP32S3 Dev Module
Default I2CSDA 8 · SCL 9
Watch out forThe port vanishes after upload

The code

There is no sketch for this page. The recovery is a button sequence, and it is worth learning by hand because it works on every board whether the auto-reset circuit does or not.

manual_download_mode.txt
1. Hold down BOOT (sometimes labelled IO0 or FLASH).
2. Tap EN (sometimes RST) and let it go.
3. Let go of BOOT.
4. Press Upload.

// Still failing? Erase the flash and start clean:
//   esptool.py --port /dev/ttyUSB0 erase_flash
// Then upload again. This clears a corrupt partition table,
// which is what a board that boot-loops after a failed OTA has.

If manual mode always works and automatic never does, the two transistors that drive EN and IO0 from the USB chip are missing or wrong on your board. Nothing in software fixes that; the sequence below is the fix.

When it does not work

The port disappears the moment the sketch runs

This is a native-USB board. The port is created by your firmware, so a sketch that crashes or sleeps takes the port with it. The button sequence brings back the ROM's own USB device, which is always there.

It worked yesterday and fails today with the same cable

Something else is holding a strapping pin. Unplug everything from GPIO 0, 2, 12 and 15 and try again. A sensor that idles low on GPIO 0 stops the board booting normally and stops uploads too.

Uploads work but the board resets over and over afterwards

Almost always power. A Wi-Fi transmit burst asks for 350 mA, and a thin cable or a laptop port that cannot give it browns the chip out. The serial log says Brownout detector was triggered, which is a power message, not a code one.

Permission denied on Linux

Your user is not in the dialout group. sudo usermod -aG dialout $USER, then log out and back in. It is not a driver problem and no amount of reinstalling fixes it.

Where this goes next

Half the failures on this page are really about which port the board became, and who decided the name. That is the next page.

Serial ports and drivers

Edit this page — content/esp32/when-uploads-fail.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32 on the forum