Scheduler String-Based API Deprecation
The scheduler’s std::string-based APIs (set_timeout, set_interval, set_retry, defer, and their cancel counterparts) are now deprecated. Use const char* string literals or uint32_t numeric IDs instead.
This deprecation affects ESPHome 2026.1.0 and later, with removal planned for 2026.7.0.
What changed
Section titled “What changed”The scheduler now uses FNV-1a hashing internally, eliminating heap allocation for timeout/interval names. The std::string overloads still work but trigger deprecation warnings and will be removed in 2026.7.0.
Migration options
Section titled “Migration options”Option 1: Use string literals (recommended for most cases)
Section titled “Option 1: Use string literals (recommended for most cases)”// ❌ Before - heap allocationthis->set_timeout("update", 1000, [this]() { this->update(); });this->cancel_timeout("update");
// ✅ After - zero allocation (string literal)this->set_timeout("update", 1000, [this]() { this->update(); }); // Same!this->cancel_timeout("update"); // Same!If you’re already using string literals, no change is needed - the const char* overload is selected automatically.
Option 2: Use numeric IDs (best for dynamic cases)
Section titled “Option 2: Use numeric IDs (best for dynamic cases)”// ❌ Before - heap allocation with str_sprintfstatic uint32_t action_id = 0;std::string name = str_sprintf("action_%u", action_id++);this->set_timeout(name, 1000, callback);this->cancel_timeout(name);
// ✅ After - zero allocation with numeric IDstatic uint32_t action_id = 0;uint32_t id = action_id++;this->set_timeout(id, 1000, callback);this->cancel_timeout(id);Critical: Don’t mix string and numeric APIs
Section titled “Critical: Don’t mix string and numeric APIs”A timeout set with std::string cannot be cancelled with const char* or uint32_t, and vice versa. They use separate internal namespaces:
// ❌ BROKEN - mixing APIsthis->set_timeout(std::string("update"), 1000, callback);this->cancel_timeout("update"); // Won't cancel! Different namespace
// ✅ CORRECT - consistent API usagethis->set_timeout("update", 1000, callback);this->cancel_timeout("update"); // WorksAll deprecated methods
Section titled “All deprecated methods”Component helper methods (used via this->set_timeout(...) in your component):
| Deprecated | Replacement |
|---|---|
set_timeout(std::string, timeout, func) | set_timeout(const char*, timeout, func) or set_timeout(uint32_t, timeout, func) |
cancel_timeout(std::string) | cancel_timeout(const char*) or cancel_timeout(uint32_t) |
set_interval(std::string, interval, func) | set_interval(const char*, interval, func) or set_interval(uint32_t, interval, func) |
cancel_interval(std::string) | cancel_interval(const char*) or cancel_interval(uint32_t) |
set_retry(std::string, wait, attempts, func) | set_retry(const char*, wait, attempts, func) or set_retry(uint32_t, wait, attempts, func) |
cancel_retry(std::string) | cancel_retry(const char*) or cancel_retry(uint32_t) |
defer(std::string, func) | defer(const char*, func) (no uint32_t overload available) |
cancel_defer(std::string) | cancel_defer(const char*) (no uint32_t overload available) |
Note: Unlike set_timeout, set_interval, and set_retry, the defer/cancel_defer helpers currently only support const char* identifiers and do not have uint32_t overloads.
Deprecation warnings
Section titled “Deprecation warnings”You’ll see warnings like:
warning: 'void esphome::Scheduler::set_timeout(Component*, const std::string&, uint32_t, std::function<void()>)' is deprecated: Use const char* or uint32_t overload instead. Removed in 2026.7.0Finding code that needs updates
Section titled “Finding code that needs updates”# Find std::string usage in scheduler callsgrep -rn "set_timeout.*std::string\|str_sprintf.*set_timeout" your_component/grep -rn "set_interval.*std::string\|str_sprintf.*set_interval" your_component/grep -rn "set_retry.*std::string\|str_sprintf.*set_retry" your_component/Why this change
Section titled “Why this change”- Eliminates heap fragmentation:
std::stringnames caused heap allocations on every timeout - Zero-allocation path:
const char*anduint32_toverloads have no heap overhead - Compact storage: 4-byte hash/ID instead of string pointer + allocation
Reference Pull Request
Section titled “Reference Pull Request”Questions?
Section titled “Questions?”If you have questions about migrating your external component, please ask in:
- ESPHome Discord - #devs channel
- ESPHome GitHub Discussions
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.