diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 6ccebd0771..b6a18c1d85 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -36,6 +36,9 @@ namespace { struct ComponentErrorMessage { const Component *component; const char *message; + // Track if message is flash pointer (needs LOG_STR_ARG) or RAM pointer + // Remove before 2026.12.0 when deprecated const char* API is removed + bool is_flash_ptr; }; struct ComponentPriorityOverride { @@ -49,6 +52,25 @@ std::unique_ptr> component_error_messages; // Setup priority overrides - freed after setup completes // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) std::unique_ptr> setup_priority_overrides; + +// Helper to store error messages - reduces duplication between deprecated and new API +// Remove before 2026.12.0 when deprecated const char* API is removed +void store_component_error_message(const Component *component, const char *message, bool is_flash_ptr) { + // Lazy allocate the error messages vector if needed + if (!component_error_messages) { + component_error_messages = std::make_unique>(); + } + // Check if this component already has an error message + for (auto &entry : *component_error_messages) { + if (entry.component == component) { + entry.message = message; + entry.is_flash_ptr = is_flash_ptr; + return; + } + } + // Add new error message + component_error_messages->emplace_back(ComponentErrorMessage{component, message, is_flash_ptr}); +} } // namespace namespace setup_priority { @@ -143,16 +165,20 @@ void Component::call_dump_config() { if (this->is_failed()) { // Look up error message from global vector const char *error_msg = nullptr; + bool is_flash_ptr = false; if (component_error_messages) { for (const auto &entry : *component_error_messages) { if (entry.component == this) { error_msg = entry.message; + is_flash_ptr = entry.is_flash_ptr; break; } } } + // Log with appropriate format based on pointer type ESP_LOGE(TAG, " %s is marked FAILED: %s", LOG_STR_ARG(this->get_component_log_str()), - error_msg ? error_msg : LOG_STR_LITERAL("unspecified")); + error_msg ? (is_flash_ptr ? LOG_STR_ARG((const LogString *) error_msg) : error_msg) + : LOG_STR_LITERAL("unspecified")); } } @@ -315,19 +341,7 @@ void Component::status_set_error(const char *message) { ESP_LOGE(TAG, "%s set Error flag: %s", LOG_STR_ARG(this->get_component_log_str()), message ? message : LOG_STR_LITERAL("unspecified")); if (message != nullptr) { - // Lazy allocate the error messages vector if needed - if (!component_error_messages) { - component_error_messages = std::make_unique>(); - } - // Check if this component already has an error message - for (auto &entry : *component_error_messages) { - if (entry.component == this) { - entry.message = message; - return; - } - } - // Add new error message - component_error_messages->emplace_back(ComponentErrorMessage{this, message}); + store_component_error_message(this, message, false); } } void Component::status_set_error(const LogString *message) { @@ -338,21 +352,8 @@ void Component::status_set_error(const LogString *message) { ESP_LOGE(TAG, "%s set Error flag: %s", LOG_STR_ARG(this->get_component_log_str()), message ? LOG_STR_ARG(message) : LOG_STR_LITERAL("unspecified")); if (message != nullptr) { - // Lazy allocate the error messages vector if needed - if (!component_error_messages) { - component_error_messages = std::make_unique>(); - } // Store the LogString pointer directly (safe because LogString is always in flash/static memory) - const char *msg_ptr = LOG_STR_ARG(message); - // Check if this component already has an error message - for (auto &entry : *component_error_messages) { - if (entry.component == this) { - entry.message = msg_ptr; - return; - } - } - // Add new error message - component_error_messages->emplace_back(ComponentErrorMessage{this, msg_ptr}); + store_component_error_message(this, LOG_STR_ARG(message), true); } } void Component::status_clear_warning() {