Skip to content

Blog

BLE Event Handler Dispatch Devirtualized

Virtual handler interfaces (GAPEventHandler, GAPScanEventHandler, GATTcEventHandler, GATTsEventHandler, BLEStatusEventHandler) have been replaced with callback-based dispatch. External components that inherit from these interfaces must update their registration approach.

This is a developer breaking change for external components in ESPHome 2026.4.0 and later.

CallbackManager: std::function Replaced with Lightweight Callback

CallbackManager and LazyCallbackManager now use a lightweight 8-byte Callback struct instead of std::function (16 bytes). External components that define their own callback registration methods using std::function should update to templates for optimal performance.

This is a breaking change for external components in ESPHome 2026.4.0 and later.

Climate and Fan Custom Mode Vectors Moved to Entity

Custom mode vectors (custom_fan_modes, custom_presets for climate; preset_modes for fan) are now stored on the entity base class instead of being rebuilt inside traits on every call. The old ClimateTraits and FanTraits setter methods are deprecated.

This is a breaking change for external components in ESPHome 2026.4.0 and later.

Modbus Helper Functions Moved to modbus::helpers

Shared helper functions and types have been moved from modbus_controller to modbus::helpers to enable reuse by other modbus-based components. Deprecated shims keep the old names working until ESPHome 2026.10.0.

This is a developer breaking change for external components in ESPHome 2026.4.0 and later.

TemplatableFn: 4-Byte Templatable Storage for Trivially Copyable Types

The TEMPLATABLE_VALUE macro now uses TemplatableFn (4 bytes) instead of TemplatableValue (8 bytes) for trivially copyable types like float, uint32_t, bool, and enums. External components that call macro-generated setters with raw C++ constants instead of going through cg.templatable() will fail to compile.

This is a breaking change for external components in ESPHome 2026.4.0 and later.

Trigger Trampolines Eliminated with build_callback_automation

Common entity trigger classes have been replaced with lightweight forwarder structs that fit inline in the callback system. The new build_callback_automation() API eliminates per-trigger object allocations. Several entity callback signatures have also changed to pass state as an argument.

This is a breaking change for external components in ESPHome 2026.4.0 and later.

FlushResult Renamed to UARTFlushResult

The FlushResult enum introduced in ESPHome 2026.3.0 has been renamed to UARTFlushResult with prefixed enum values to follow ESPHome's naming conventions and avoid macro collisions.

This is a breaking change for external components in ESPHome 2026.4.0 and later.

wake_loop Moved from Socket Component into Core

wake_loop_threadsafe() and related wake primitives have moved from the socket component into core. The require_wake_loop_threadsafe() opt-in is deprecated (now a no-op) — wake works unconditionally on all platforms.

This is a breaking change for external components in ESPHome 2026.4.0 and later.

Application Name and Friendly Name Now Return StringRef

App.get_name() and App.get_friendly_name() now return const StringRef & instead of const std::string &. Most code compiles unchanged because StringRef provides .c_str(), .size(), .empty(), and implicit conversion to std::string. However, binding the result to const std::string & silently creates a heap-allocated temporary — update these references to const auto & to avoid the allocation.

This is a breaking change for external components in ESPHome 2026.3.0 and later.