Entity Names Kept in Flash on ESP8266
Entity names are now stored in flash on ESP8266 instead of RAM. EntityBase::get_name() is deprecated on all platforms and replaced by get_name_to() for a copy of the name and get_log_name() for logging. It keeps working everywhere with a deprecation warning until it is removed in 2027.5.0. On ESP8266 the first call for an entity makes a RAM copy of its name and keeps it, so callers pay back the RAM this change saves for that entity.
This is a developer breaking change for external components in ESPHome 2026.11.0 and later.
Background
Section titled “Background”PR #20423: Keep entity names in flash on ESP8266
On ESP8266, string literals are copied into RAM at boot, so every entity name used RAM for the life of the device. Code generation now wraps names in ESPHOME_PSTR, which keeps them in flash on ESP8266 and changes nothing on other platforms. A device with 27 entities saves 316 bytes of RAM.
Flash on ESP8266 can only be read in aligned 32 bit words. Code that reads a name one byte at a time (strcmp, memcpy, std::string, iterating, hashing) crashes there with a load or store exception. Passing the name to a %s log argument is safe, because the logger reads flash strings correctly. The same approach was used for icons and device classes in Icon and Device Class Getter Migration.
What’s Changing
Section titled “What’s Changing”Deprecated methods (all platforms, removal 2027.5.0)
Section titled “Deprecated methods (all platforms, removal 2027.5.0)”| Method | Replacement |
|---|---|
get_name() used in a log call | LOG_STR_ARG(get_log_name()) |
get_name() for anything else | get_name_to(buffer) |
name_.c_str() from a subclass | LOG_STR_ARG(get_log_name()) |
name_ is now a ProgmemStringRef
Section titled “name_ is now a ProgmemStringRef”The protected EntityBase::name_ member is now a ProgmemStringRef: a pointer and a length with no operations that read the characters. Comparing it, copying it or reading its characters through name_ no longer compiles, on any platform, so these mistakes are caught at build time instead of crashing on ESP8266. Its c_str() still compiles with a deprecation warning until 2027.5.0, for subclasses that log this->name_.c_str(). It returns the same pointer as before, so use it only as a %s log argument: strcmp(this->name_.c_str(), ...) or std::string(this->name_.c_str()) still compiles and still crashes on ESP8266.
New APIs
Section titled “New APIs”// Logging: no copy, safe on every platformESP_LOGD(TAG, "'%s' updated", LOG_STR_ARG(this->get_log_name()));
// Read the name: copied into name_buf on ESP8266, points at the original elsewhere.// Always use the returned StringRef, not name_buf.char name_buf[ENTITY_NAME_BUF_SIZE];StringRef name = entity->get_name_to(name_buf);
// Write the name into a larger buffer, returns the length writtensize_t len = entity->write_name_to(buf, sizeof(buf));
// Compare the name without copying itif (entity->name_equals(other)) { // ...}ENTITY_NAME_BUF_SIZE is 121 bytes, since entity names are limited to 120 bytes.
MQTTComponent::friendly_name_() deprecated
Section titled “MQTTComponent::friendly_name_() deprecated”The protected MQTTComponent::friendly_name_() helper is deprecated in favor of log_name_(), which returns a const LogString * for log calls:
ESP_LOGW(TAG, "'%s': not ready", LOG_STR_ARG(this->log_name_()));Like get_name(), it keeps working until it is removed in 2027.5.0, and on ESP8266 it uses the same RAM copy.
PIDAutotuner::set_autotuner_id() takes a const LogString *
Section titled “PIDAutotuner::set_autotuner_id() takes a const LogString *”PIDAutotuner::set_autotuner_id() took a std::string and now takes a const LogString *. This changed right away, with no deprecation period, so a caller that passes a string no longer compiles. Pass the entity’s log name instead:
autotuner->set_autotuner_id(this->get_log_name());Sprinkler::valve_name() deprecated
Section titled “Sprinkler::valve_name() deprecated”Sprinkler::valve_name() returned a pointer to the valve’s name, which is now in flash on ESP8266. Like get_name(), it is deprecated until 2027.5.0, and on ESP8266 it uses the same RAM copy. Use valve_log_name() for logging, or control_switch(n)->get_name_to(buffer) for a copy:
ESP_LOGD(TAG, "Valve '%s' on", LOG_STR_ARG(sprinkler->valve_log_name(n)));Who This Affects
Section titled “Who This Affects”External components that:
- Call
get_name()on any entity: deprecation warning on all platforms - Read
this->name_from an entity subclass: deprecation warning forc_str(), compile error for anything else - Call
friendly_name_()from anMQTTComponentsubclass - Call
Sprinkler::valve_name() - Call
PIDAutotuner::set_autotuner_id(): compile error until the argument is aconst LogString *
Lambdas in YAML configurations that call get_name() on an entity (for example id(my_sensor).get_name()) need the same change.
Migration Guide
Section titled “Migration Guide”// BeforeESP_LOGD(TAG, "'%s' updated", this->get_name().c_str());ESP_LOGD(TAG, "'%s' updated", this->name_.c_str());this->send_name_(sensor->get_name());bool match = sensor->get_name() == other;
// AfterESP_LOGD(TAG, "'%s' updated", LOG_STR_ARG(this->get_log_name()));char name_buf[ENTITY_NAME_BUF_SIZE];this->send_name_(sensor->get_name_to(name_buf));bool match = sensor->name_equals(other);Supporting Multiple ESPHome Versions
Section titled “Supporting Multiple ESPHome Versions”#if ESPHOME_VERSION_CODE >= VERSION_CODE(2026, 11, 0) ESP_LOGD(TAG, "'%s' updated", LOG_STR_ARG(this->get_log_name()));#else ESP_LOGD(TAG, "'%s' updated", this->get_name().c_str());#endif
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2026, 11, 0) char name_buf[ENTITY_NAME_BUF_SIZE]; this->send_name_(sensor->get_name_to(name_buf));#else this->send_name_(sensor->get_name());#endifTimeline
Section titled “Timeline”- ESPHome 2026.11.0 (November 2026):
get_name(),MQTTComponent::friendly_name_(),Sprinkler::valve_name()andProgmemStringRef::c_str()deprecated, new APIs available - ESPHome 2027.5.0 (May 2027):
get_name(),MQTTComponent::friendly_name_(),Sprinkler::valve_name()andProgmemStringRef::c_str()removed on all platforms
Finding Code That Needs Updates
Section titled “Finding Code That Needs Updates”grep -rn 'get_name()' your_component/grep -rn 'name_\.c_str()\|friendly_name_()\|valve_name(' your_component/grep -rn 'get_name()' --include='*.yaml' your_config_dir/get_name() also exists on unrelated classes such as Application, Device and light effects; only the entity method changes.
Questions?
Section titled “Questions?”If you have questions about migrating your external component, please ask in:
- ESPHome Discord - #devs channel
- ESPHome GitHub Discussions
Related Documentation
Section titled “Related Documentation”Copyright © 2026 ESPHome - A project from the Open Home Foundation
Comments
Feel free to leave a comment here to discuss this post with others. You can ask questions, share your experience, or suggest improvements. If you have a question about a specific feature or issue, please consider using the ESPHome Discord. Stick to English and follow ESPHome's code of conduct. These comments exist on a discussion on GitHub, so you can also comment there directly if you prefer.