From da06bb9c7f66d81b22784b2fa2ecec4316c44b43 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 3 May 2026 18:19:24 -0500 Subject: [PATCH] [ota] Skip safe_shutdown after partition-table OTA For OTA_TYPE_UPDATE_PARTITION_TABLE the success path runs nvs_flash_deinit() before the final write, which leaves every preference handle held by other components invalid. App.safe_reboot() calls on_safe_shutdown() which tries to flush preferences, and each flush fails with ESP_ERR_NVS_INVALID_HANDLE -- noisy log spam during the reboot window. App.reboot() skips the safe-shutdown callbacks and goes straight to esp_restart(). For partition-table OTAs there is nothing useful to flush (NVS handles are already dead, the device is moments from a reboot anyway), so reboot directly. App-OTA path is unchanged: safe_reboot() still runs on_safe_shutdown so preferences are saved on the way out. --- esphome/components/esphome/ota/ota_esphome.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index e6e75bd6e0..3ce3f2302d 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -498,6 +498,13 @@ void ESPHomeOTAComponent::handle_data_() { this->notify_state_(ota::OTA_COMPLETED, 100.0f, 0); #endif delay(100); // NOLINT +#ifdef USE_OTA_PARTITIONS + if (ota_type == ota::OTA_TYPE_UPDATE_PARTITION_TABLE) { + // Skip on_safe_shutdown: nvs_flash_deinit() has already invalidated open NVS handles, so + // preferences flush would emit ESP_ERR_NVS_INVALID_HANDLE for every entry. Reboot directly. + App.reboot(); + } +#endif App.safe_reboot(); error: