Why are my variables passed as empty strings when used in a service call parameter?

I have a script, which has variables. But when I call a service in the script, using a variable as parameter in the data block, an empty string is passed instead of the actual content of the variable. This happens now on the media_player.play_media service where I try to pass the contents of a variable as media_content_id; But I encountered this before in another script where i call the denon_avr.get_command.

Am I missing something? As this looks to me as quite basic functionality, and nothing in the docs Iā€™ve read seem to indicate otherwise.

In the current script, which takes a variable station as text inputfield, I define a variable stations_map :

internet_radio_chooser:
  alias: Start Internet Radio station on current Internet Radio target
  variables:
    stations_map:
      Willy:
        marantz:
          category: 3
          station: 0
        radiobrower_id: "07b53b92-2892-4996-8e60-d3a626c46cb4"
      Willy Class X:
        marantz:
          category: 3
          station: 1
        radiobrowser_id: "7bd23fe4-3173-4cd5-a548-fe0be1495342"
      Studio Brussel:
        marantz:
          category: 3
          station: 2
        radiobrowser_id: "a392fb2c-fff2-47ad-8492-4a8491ba129e"
      Studio Brussel Bruut:
        marantz:
          category: 3
          station: 3
        radiobrowser_id: "21b70fdc-d2b1-49e2-9afd-7883fd2d0e03"

Then depending on the selected target for the internet radio station, I execute the right service with the right parameters from the stations_map variable:
When the target is set to ā€œWoonkamerā€ I execute another script to tune the Marantz amp in that room to the selected station:

  sequence:
    - alias: Choose target specific actions
      choose:
        - conditions:
            - condition: state
              entity_id: input_select.internet_radio_target
              state: Woonkamer
          sequence:
            - alias: Tune station on Marantz Main zone
              service: script.marantz_iradio_my_station_chooser
              data:
                entity: media_player.marantz_sr5008_zone_1
                category_index: "{{ stations_map[station].marantz.category }}"
                station_index: "{{ stations_map[station].marantz.station }}"

Which works perfectly. The stations_map[station].marantz.category and .station values are succesfully passed to the script and everything works as expected.

However, for a Sonos speaker in room ā€œBadkamerā€, I want to call the radiobrowser media_player.play_media service:

        - conditions:
            - condition: state
              entity_id: input_select.internet_radio_target
              state: Badkamer
          sequence:
            - alias: Start Radio Browser source for station
              service: media_player.play_media
              data:
                media_content_id: media-source://radio_browser/{{ stations_map[station].radiobrowser_id }}
                media_content_type: audio/mpeg
              entity_id: media_player.badkamer

And this does not work. According to the script trace, {{ stations_map[station].radiobrowser_id }} resolves in an empty string :

 Result:

params:
  domain: media_player
  service: play_media
  service_data:
    media_content_id: media-source://radio_browser/
    media_content_type: audio/mpeg
    entity_id:
      - media_player.badkamer
  target:
    entity_id:
      - media_player.badkamer
running_script: false

Also calling it with only the variable:

    media_content_id: "{{ stations_map[station].radiobrowser_id }}"

trace tells me it is empty:

 Result:

params:
  domain: media_player
  service: play_media
  service_data:
    media_content_id: ''
    media_content_type: audio/mpeg
    entity_id:
      - media_player.badkamer
  target:
    entity_id:
      - media_player.badkamer
running_script: false

I donā€™t understand? Why does it work when calling a script, and not when calling another service? While I understand from the documentation that this should perfectly work ?

Link to the docs and section youā€™re referring to.

Note that thereā€™s a difference between script variables (internal to the script) and fields (passed externally).

And be careful with extra spaces. They might be considered such and added to the path.

When I read Script Syntax - Variables and Scripts - Configuration Variables, I understand that when I define a variable on script level I should be able to use it in templates within the script as the scope of the variable is global to the script.
The example provided in the first link does, for what I can see, exactly what I try to do: they call a service and pass a variable value brightness using the template {{ brightness }} to the service light.turn_on.
If somehow the variable would not be in scope, in case the template would not be applied during the call to the service in the script itself but after that, inside the service routine itself, where the variable is not known, I would expect an error similar to ā€œunknown variableā€ since it is not defined there or global to HA;

Iā€™m not sure what differences there are at the point where I have this problem?

There are no extra spaces in the string I pass to media_content_id. But even if I only pass the variable using the template {{ stations_map[station].radiobrowser_id }} trace shows me that template is translated as '' instead of the expected value of the variable.

You have spaces between {{ and station, and also in the end.
If it is one of the cases where that first space is actually seen as a space, then it will split the text in two and your inserted text will be an extra parameter that is ignored.

As an experienced Ansible user applying Jinja templates inside yaml on a daily base, Iā€™m certain that "{{ variable_name }}" is the same as "{{variable_name}}". For the Ansible linter at least it is even forbidden to format it without spaces.
This way of formatting the template is used everywhere in the Jinja documentation. Also in all examples in the HA docs, spaces are also used around variables in templates.

But just to be sure, I tested removing the spaces from the template and passed the variables as such:

media_content_id: "{{stations_map[station].radiobrowser_id}}"

But the result is exactly the same; an empty string is passed according to the script trace.

I wasnā€™t sure whether youā€™ve been having problems passing data into the script, using variables within the script, or both. Also, I mentioned that, because the HA docs can be quite confusing on this front. Iā€™ve gotten stuck on this before too.

HA doesnā€™t care either. Thereā€™s no difference.

What would (could) make a difference is:

media_content_id: " {{ stations_map[station].radiobrowser_id }} "

Note the space between " and {{.

Normally youā€™d do it like this (hence my callout about fields):

          sequence:
            - alias: Tune station on Marantz Main zone
              service: script.marantz_iradio_my_station_chooser
              data:
                variables:
                  entity: media_player.marantz_sr5008_zone_1
                  category_index: "{{ stations_map[station].marantz.category }}"
                  station_index: "{{ stations_map[station].marantz.station }}"

Could rather post the full scripts and automations at play here, not snippets?

I have posted the whole script in the original post. If you concatenate the 3 first snippets I posted, it is the whole script. The only part that I left out is the mode, icon and fields part as I didnā€™t think it to be relevant as I already mentioned that the script accepts a field station:

  mode: single
  icon: mdi:radio
  fields:
    station:
      selector:
        text:
      required: true
      name: Station
      description: Station name of Radio station to tune to

There are no automations at play here, I call the script from different buttons, like this:

type: custom:button-card
entity_picture: /local/images/logo_willy.png
show_entity_picture: true
tap_action:
  action: call-service
  service: script.internet_radio_chooser
  data:
    station: Willy

I can also post the marantz_iradio_my_station_chooser script here, which I call in the first choose-sequence, but I donā€™t think that will help? The calling of that script with the variable used in 2 parameters of that script works as expected. There the variable template is correctly expanded.

If I try to do that, I get this error when executing the script:

extra keys not allowed @ data[ā€˜variablesā€™]

If you are testing with the first station, then you have a typo.

radiobrower_id
2 Likes

:flushed: :face_with_symbols_over_mouth: :triumph:
Hours of my life did I waste on thisā€¦
That was indeed the problem. Many many thanks for spotting that!

FYI you can avoid these issues by using .get on dictionaries. Secondly, there should have been an error in your logs saying "radiobroswer_id" is not defined in a template error.

Open your Home Assistant instance and show your Home Assistant logs.