Fix “Image file at 0x1000 doesn't look like an image file”
esptool found no ESP image header at that address — usually the wrong offset for the chip (0x0 vs 0x1000) or a merged/MicroPython .bin flashed to the wrong place.
Community draft — report a mistake
What you see
esptool.py v4.8.1
Serial port COM9
Connecting...
Chip is ESP32-S3 (QFN56) (revision v0.2)
Stub running...
Configuring flash size...
Flash will be erased from 0x00001000 to 0x0017efff...
Warning: Image file at 0x1000 doesn't look like an image file, so not changing any flash settings.
Compressed 1564672 bytes to 1023745...
Wrote 1564672 bytes (1023745 compressed) at 0x00001000 in 13.1 seconds (effective 955.6 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...esptool.py v4.8.1 Serial port COM9 Connecting... Chip is ESP32-S3 (QFN56) (revision v0.2) Stub running... Configuring flash size... Flash will be erased from 0x00001000 to 0x0017efff... Warning: Image file at 0x1000 doesn't look like an image file, so not changing any flash settings. Compressed 1564672 bytes to 1023745... Wrote 1564672 bytes (1023745 compressed) at 0x00001000 in 13.1 seconds (effective 955.6 kbit/s)... Hash of data verified. Leaving... Hard resetting via RTS pin...
Each ESP chip family looks for its second-stage bootloader at a fixed flash address: 0x1000 on the classic ESP32 and ESP32-S2, 0x0 on the newer S3, C3 and C6. esptool checks for an image header at that address so it can patch the flash settings.
This warning means the header was not where it should be. The write itself finishes, but the chip will not find a bootloader. It is almost always the wrong offset for the chip, or a merged file written above 0x0.
Quick fix — try in order
- 1
Use the right start address for your chip
The bootloader (or a merged image) goes at 0x1000 on ESP32 and ESP32-S2, but at 0x0 on ESP32-S3, C3, C6 and H2. Flashing an S3 image at 0x1000 gives this warning and a board that never boots.
- 2
MicroPython: copy the address from the download page
micropython.org lists the exact command per chip. For ESP32-S3 and C3 firmware it is
write_flash 0 firmware.bin; for classic ESP32 it iswrite_flash 0x1000 firmware.bin. - 3
Merged/factory .bin goes at 0x0
A file named *.merged.bin or *-factory.bin contains bootloader, partition table and app together. Write it at 0x0 on every chip.
- 4
Erase first, then flash once more
Run
esptool.py erase_flash, then flash at the correct address. Leftovers from a wrong-offset write can keep the old partition table around.
Why it happens
Why only a warning and not an error?
esptool can flash any data anywhere. It only uses the header at the bootloader address to patch flash mode and size. When there is no header there, it skips the patch and writes the bytes anyway — so the upload “succeeds” but the board will not boot.
What happens on the board?
The ROM looks for a bootloader at its fixed address, finds the wrong bytes and prints “invalid header: 0xffffffff” or similar in a loop. See invalid header.
Board-specific notes
ESP32-S3 / C3 / C6: Bootloader at 0x0, partitions at 0x8000, app at 0x10000.
ESP32 / ESP32-S2: Bootloader at 0x1000, partitions at 0x8000, app at 0x10000.
Did this fix it?
Thanks — that helps us keep this page right.