mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 17:05:36 +00:00
[web_server] Reset OTA backend on new upload to avoid bricked device after interrupted OTA
If a captive_portal or web_server OTA upload is interrupted mid-stream (e.g. TCP connection reset), the shared OTARequestHandler's ota_backend_ is left open. When the browser resends the multipart POST, the guard 'index == 0 && !ota_backend_' skipped re-initialization, so new bytes were written at the previous session's offset. The Updater's end() then reports success with a concatenated image in flash, bricking the device on reboot. Abort and reset any in-progress backend whenever a new multipart upload starts (index == 0) so the fresh upload begins a clean OTA session.
This commit is contained in:
@@ -114,7 +114,18 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Platf
|
||||
uint8_t *data, size_t len, bool final) {
|
||||
ota::OTAResponseTypes error_code = ota::OTA_RESPONSE_OK;
|
||||
|
||||
if (index == 0 && !this->ota_backend_) {
|
||||
if (index == 0) {
|
||||
// A new multipart upload is starting. If a previous upload was interrupted
|
||||
// (e.g. TCP reset) the backend from that session may still be open; tear it
|
||||
// down so flash state doesn't get concatenated with the new image (which
|
||||
// can produce a technically-valid-sized but corrupted firmware that
|
||||
// bricks the device once it reboots).
|
||||
if (this->ota_backend_) {
|
||||
ESP_LOGW(TAG, "New OTA upload received while previous session was still open; aborting previous session");
|
||||
this->ota_backend_->abort();
|
||||
this->ota_backend_.reset();
|
||||
}
|
||||
|
||||
// Initialize OTA on first call
|
||||
this->ota_init_(filename.c_str());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user