Automation: referencing a variable inside another variable (Error: TypeError: unhashable type: 'Wrapper')

I was trying to add a volume setting to my alexa notification service, and was trying to be cute and preserve the old volume of the echo i am calling and then set it back after the notification happens. I am having an issue with setting a variable that always seems to error out with:

Error: TypeError: unhashable type: 'Wrapper'

Here is the part of the script where it fails, specifically at calculating the previous_volume:

alias: HELPER - activate_alexa_actionable_notification
description: Used to call Alexa Actionable Notifications.  Sends message to Alexa
sequence:
  - alias: alexa actions variables
    variables:
      echo_device: "{{ alexa_device | default('media_player.living_room_echo') }}"
      suppress_ok: "{{ suppress_confirmation | default(false) }}"
      echo_volume: "{{ alert_volume | default(0.5) }}"
      previous_volume: |-
        {% if state_attr(echo_device, 'volume_level') is not none %}
          {% set previous_volume = state_attr( echo_device , 'volume_level') %}
        {% else %}
          {% set previous_volume = 0.4 %}
        {% endif %}  
        {{ previous_volume}}

any clues on why it is doing this?

Anyone wanting to help will need the whole script as the part you have shown seems to use variables that we know nothing about.

Also, need to see how it is being called.

Here’s the rest of the script, but the traces show the error at the variable declaration section i pasted. The error is definitely in the way i am trying to calculate previous_volume, i am pretty sure i am missing something in the way you use variables inside other variables…

alias: HELPER - activate_alexa_actionable_notification
description: Used to call Alexa Actionable Notifications.  Sends message to Alexa
sequence:
  - alias: alexa actions variables
    variables:
      echo_device: "{{ alexa_device | default('media_player.living_room_echo') }}"
      suppress_ok: "{{ suppress_confirmation | default(false) }}"
      echo_volume: "{{ alert_volume | default(0.5) }}"
      previous_volume: |-
        {% if state_attr(echo_device, 'volume_level') is not none %}
          {% set previous_volume = state_attr( echo_device , 'volume_level') %}
        {% else %}
          {% set previous_volume = 0.4 %}
        {% endif %}  
        {{ previous_volume}}
  - action: input_text.set_value
    target:
      entity_id: input_text.alexa_actionable_notification
    data:
      value: >-
        {"text": "{{ text }}", "event": "{{ event_id }}",
        "suppress_confirmation": "{{ suppress_ok }}"}  
  - action: media_player.volume_set
    metadata: {}
    data:
      volume_level: "{{ echo_volume }}"
    target:
      entity_id: "{{ echo_device }}"
  - action: media_player.play_media
    target:
      entity_id: "{{ echo_device }}"
    data:
      media_content_type: skill
      media_content_id: REDACTED
  - action: media_player.volume_set
    metadata: {}
    data:
      volume_level: "{{ previous_volume }}"
    target:
      entity_id: "{{ echo_device }}"
fields:
  text:
    description: The text you would like alexa to speak.
    example: What would you like the thermostat set to?
  event_id:
    description: Correlation ID for event responses
    example: ask_for_temperature
  alexa_device:
    description: Alexa device you want to trigger
    example: media_player.kitchen_echo_show
  suppress_confirmation:
    description: Set true if you want to suppress 'okay' confirmation
    example: "true"
  alert_volume:
    selector:
      number:
        min: 0
        max: 1
        step: 0.01
    name: alert_volume
    description: The volume for the notification
    default: 0.5
mode: queued
max: 20


Hi sebastian,

Loose the “set” in a template in the variable. The set is implied, so to speak…

      previous_volume: |-
        {% if state_attr(echo_device, 'volume_level') is not none %}
          {{ state_attr( echo_device, 'volume_level') | float(0) }}
        {% else %}
          0.4

May not need the float, but this makes sure it’s a float and also prevents an error by defaulting to something. You can pick other than 0 for the default…

1 Like

yeah, i was using the set as a last straw, since i didn’t know what was causing the issue. it turns out that casting it to float is what made the difference. since i cast it to float with a default, i can simplify the entire bit to this:

  previous_volume: "{{ state_attr(echo_device, 'volume_level') | float(0.4) }}"

appreciate the help!

1 Like