!remove example from documentation fails when using substitutions

Hello,

I’m trying to understand how !remove is supposed to work.
To do so, I reproduced exactly the example from the ESPHome documentation:

But the example does not work.

I created a file switch.yaml:

switch:
  - platform: restart
    id: restart_switch
    name: "Living Room Restart"

Then test.yaml:

esphome:
  name: test-remove

packages: !include switch.yaml  # see above

esp32:
  board: wt32-eth01
  framework:
    type: esp-idf

#...

substitutions:
  disable_reboot: true

switch:
  - id: !remove ${disable_reboot and 'restart_switch'}

I have this error:

Failed config

switch.unknown: [source test.yaml:23]

  Source for removal of ID 'restart_switch' was not found.
  id: !remove restart_switch

If I use the id without any substitution:

switch:
  - id: !remove restart_switch

It works.

Moreover, I dont see how not to remove the switch with this mechanism.
I tried:

substitutions:
  disable_reboot: false

switch:
  - id: !remove ${disable_reboot and 'restart_switch'}

I got:

switch.unknown: [source test.yaml:23]

  Source for removal of ID 'False' was not found.
  id: !remove False

I tried:

substitutions:
  disable_reboot: 

switch:
  - id: !remove ${disable_reboot and 'restart_switch'}

I got:

switch.unknown: [source test.yaml:23]

  Source for removal of ID 'None' was not found.
  id: !remove None

Questions

  • Is the documentation example wrong or incomplete?
  • Does !remove support substitutions at all?
  • Is there a way to conditionally avoid removal?
  • Should the expression return an empty string instead of False / None ?

I cannot find any additional information about how !remove is parsed or how it interacts with substitutions and Jinja expressions.

Any help would be greatly appreciated.

I’ve done additional tests, and I found something very strange that shows an inconsistency in the substitution resolution order.

Test 1

test.yaml

substitutions:
  identifier: restart_switch

switch:
  - id: !remove ${identifier}

switch.yaml

switch:
  - platform: restart
    id: restart_switch
    name: "Living Room Restart"

:x: doesn’t work

Test 2

test.yaml

substitutions:
  identifier: restart_switch

switch:
  - id: !remove ${identifier}

switch.yaml

switch:
  - platform: restart
    id: ${identifier}
    name: "Living Room Restart"

:white_check_mark: works

This means when the config is validated the substitutions are not resolved so ${identifier} is different from restart_switch

It was a bug in 2025.10.x, it is resolved in 2025.11.x (#11203)