Using response_var from script to populate attribute of templated triggered binary sensors

I use a script to (successfully) get LLDP data from OpenWrt devices via Ubus, and want to make that data available to templates further down the line, so I’m attempting to create some templated entities with the LLDP data as attribute.

Passing the data from the script I get an error (full below), that would seem to indicate, that I should pass a dictionary, so I changed the relevant line from
lldp: {{ (lldp.stdout | from_json).lldp.interface ))
to:

alias: Get LLDP from OpenWrt
sequence:
  - data:
      subsystem: file
      method: exec
      parameters:
        command: /usr/sbin/lldpctl
        params:
          - "-f"
          - json
    response_variable: lldp
    target:
      entity_id: "{{ target }}"
    action: openwrt.ubus
  - variables:
      lldp: >
        {{ dict({}, interface=(lldp.stdout | from_json).lldp.interface ) }}
  - stop: End
    response_variable: lldp
mode: parallel
fields:
  target:
    selector:
      entity: {}
    name: Target OpenWrt Entity
    required: true

, but I still get the error
Get LLDP from OpenWrt: Error executing script. Error for call_service at pos 1: Failed to process the returned action response data, expected a dictionary, but got <class 'NoneType'>

and then again, the same error with a different prefix:
Trigger Update Coordinator: Error executing script. Error for call_service at pos 3:

When I run this script separately in developer tools, the output sure does look like a valid dictionary with my wanted LLDP data.

The whole context this is happening in:

  template:
    - trigger:
        platform: time_pattern
        minutes: "/1"
      action:
        - service: script.get_lldp_from_openwrt
          data:
            target: binary_sensor.openwrt_wrsw
          response_variable: lldp_wrsw
# Several more service calls like the above with different hostnames (wrsw = workroom switch)
      binary_sensor:
        - name: OpenWrt WRSW UBUS LLDP Topo
          unique_id: openwrt_wrsw_ubus_lldp
          state: "{{ states('binary_sensor.openwrt_wrsw') }}"
          attributes:
            data: "{{ lldp_wrsw }}"
# Several more binary sensors for different Openwrt Devices

I had built a prototype of something with similar value-passing a year ago, and got it working back then in my throw-away scratchpad installation, but can’t figure out anymore how I did it back then.

FINAL EDIT: Solved with help from the others:
The above works and is correct, but fails for all the sensors, if the service call for even one of the LLDP-Hosts fails. The logs don’t make that clear, but the Trace in the script menu adds more vital detail to the error in that case. I’m adding failure-resiliance mechanisms now. Thanks again, learnt something from everybody below!

Not sure what you are attempting to do. A response_variable is always a dict, your first action already provides a response, and the rest of your actions are doing what to me seems unnecessary formatting of the data. Simply remove both variables and stop and do all of your processing in the state and data templates?

I think the problem is that something is wrong with the command you’re sending through the first action, which makes it not return any response at all (hence the complaint about expecting a dictionary but receiving none).

The stop seems necessary, otherwise I never get output in Developer tools

Also, I tried duplicating the from_json + unwrapping line into the state attribute line like so:

        - name: OpenWrt WRBR UBUS LLDP Topo
          unique_id: openwrt_wrbr
          state: "{{ states('binary_sensor.openwrt_wrbr') }}"
          attributes:
            data: "{{ (lldp_wrbr.stdout | from_json).lldp.interface }}"

But that leads to the same error about classType none. Also,I thought it better to do the stdout | from_json-bit in the script instead of having to duplicate it into every sensor.

Hmm, got a bit confused there I think, as I thought the first part was also a template entity.

What does the traces say for the script? Is the content of changed variables always what you are expecting? Which step is it that fails?

You can’t overwrite variables. You’re attempting to overwrite lldp in the 2nd variable action. Change that to some other variable and use that other variable as the response_variable.

Every minute (when the trigger runs) I also get (along the with 2 already posted errors) this traceback:

Logger: homeassistant
Source: core.py:2799
First occurred: 8:29:00 PM (1 occurrences)
Last logged: 8:29:00 PM

Error doing job: Task exception was never retrieved (None)
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/template/coordinator.py", line 115, in _handle_triggered_with_script
    if script_result := await self._script.async_run(run_variables, script_context):
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1801, in async_run
    return await asyncio.shield(create_eager_task(run.async_run()))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 464, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 528, in _async_step
    self._handle_exception(
    ~~~~~~~~~~~~~~~~~~~~~~^
        ex, continue_on_error, self._log_exceptions or log_exceptions
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 558, in _handle_exception
    raise exception
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 526, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 764, in _async_call_service_step
    response_data = await self._async_run_long_action(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<9 lines>...
    )
    ^
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 727, in _async_run_long_action
    return await long_task
           ^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/core.py", line 2795, in async_call
    response_data = await coro
                    ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/core.py", line 2838, in _execute_service
    return await target(service_call)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 718, in _service_handler
    response = await self._async_start_run(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        variables=service.data, context=service.context, wait=True
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 674, in _async_start_run
    script_result = await coro
                    ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 707, in _async_run
    return await self.script.async_run(script_vars, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1801, in async_run
    return await asyncio.shield(create_eager_task(run.async_run()))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 464, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 528, in _async_step
    self._handle_exception(
    ~~~~~~~~~~~~~~~~~~~~~~^
        ex, continue_on_error, self._log_exceptions or log_exceptions
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 558, in _handle_exception
    raise exception
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 526, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 764, in _async_call_service_step
    response_data = await self._async_run_long_action(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<9 lines>...
    )
    ^
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 727, in _async_run_long_action
    return await long_task
           ^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/core.py", line 2799, in async_call
    raise HomeAssistantError(
    ...<5 lines>...
    )
homeassistant.exceptions.HomeAssistantError: Failed to process the returned action response data, expected a dictionary, but got <class 'NoneType'>

No change in symptoms. I appended “_res” to the last 2 uses of ‘lldp’, renaming it to ‘lldp_res’

Then you have a template error you’re missing in the logs

Just those 3 errors, with incrementing number in the “shows up 8 times” part

I cleared the logs, and waited a few minutes, and I get just the 3 posted errors, once per minute.

Also, the entire script and sensor is in the first post, and there is not much templating in there,

Thank you already for your time and attention looking in to this!

Edit, Ok, I’ll go check the log file in the container.

look at the raw logs, your template is definitely failing which is making the variable empty, which results in the errors you’re seeing.

You can also just try this, which will get rid of the other 3 errors. However your data will still likely be None.

alias: Get LLDP from OpenWrt
sequence:
  - data:
      subsystem: file
      method: exec
      parameters:
        command: /usr/sbin/lldpctl
        params:
          - "-f"
          - json
    response_variable: lldp
    target:
      entity_id: "{{ target }}"
    action: openwrt.ubus
  - variables:
      lldp_res:
        interface: "{{ (lldp.stdout | from_json).lldp.interface }}"
  - stop: End
    response_variable: lldp_res

If by that you mean the homeassistant.log in my podman, it does not show more data:

                                                                                                                                                                    
2025-01-15 20:43:00.530 ERROR (MainThread) [homeassistant.components.script.get_lldp_from_openwrt] Get LLDP from OpenWrt: Error executing script. Error for call_service at pos 1: Failed to process the returned action response data, expected a dictionary, but got <class 'NoneType'>                                                                                          
2025-01-15 20:43:00.532 ERROR (MainThread) [homeassistant.helpers.script.trigger_update_coordinator] Trigger Update Coordinator: Error executing script. Error for call_service at pos 3: Failed to process the returned action response data, expected a dictionary, but got <class 'NoneType'>                                                                                   
2025-01-15 20:43:00.535 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved (None)                                               
Traceback (most recent call last):                                                                                                                                  
  File "/usr/src/homeassistant/homeassistant/components/template/coordinator.py", line 115, in _handle_triggered_with_script                                        
    if script_result := await self._script.async_run(run_variables, script_context):                                                                                
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                 
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1801, in async_run                                                                            
    return await asyncio.shield(create_eager_task(run.async_run()))                                                                                                 
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                 
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 464, in async_run                                                                             
    await self._async_step(log_exceptions=False)                                                                                                                    
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 528, in _async_step                                                                           
    self._handle_exception(                                                                                                                                         
    ~~~~~~~~~~~~~~~~~~~~~~^                                                                                                                                         
        ex, continue_on_error, self._log_exceptions or log_exceptions                                                                                               
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                               
    )                                                                                                                                                               
    ^                                                                                                                                                               
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 558, in _handle_exception                                                                     
    raise exception                                                                                                                                                 
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 526, in _async_step                                                                           
    await getattr(self, handler)()                                                                                                                                  
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 764, in _async_call_service_step                                                              
    response_data = await self._async_run_long_action(                                                                                                                                                                                                                                                  
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                              
    ...<9 lines>...                                                                                                                                                                                                                                    
    )                                                                             
    ^                                                                                                                                               
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 727, in _async_run_long_action                                                                                                                
    return await long_task                                                                                                 
           ^^^^^^^^^^^^^^^                                                                                                                                          
  File "/usr/src/homeassistant/homeassistant/core.py", line 2795, in async_call                                                                                                                                                                        
    response_data = await coro                                                                                                                                                                                      
                    ^^^^^^^^^^                                                                                                                                                                                                                                                                          
  File "/usr/src/homeassistant/homeassistant/core.py", line 2838, in _execute_service                                                                                                                                                                  
    return await target(service_call)                                                                                      
           ^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                               
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 718, in _service_handler                                                                               
    response = await self._async_start_run(                                                                                                                                                                         
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                                                                                                                             
        variables=service.data, context=service.context, wait=True                                                         
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                                                                                                      
    )                                                
    ^                                                                                                                                                                                                                                                  
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 674, in _async_start_run                                                                               
    script_result = await coro                                                                                                                                                                                      
                    ^^^^^^^^^^                               
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 707, in _async_run                                                                                                                                                   
    return await self.script.async_run(script_vars, context)                                                                                                                                                                                                                                            
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                               
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1801, in async_run                                                                                                                                                                                                                
    return await asyncio.shield(create_eager_task(run.async_run()))                         
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                                                                                                     
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 464, in async_run                                                                                                                                                                
    await self._async_step(log_exceptions=False)                                                                                                    
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 528, in _async_step                                                                                                
    self._handle_exception(                                                                                                
    ~~~~~~~~~~~~~~~~~~~~~~^                                  
        ex, continue_on_error, self._log_exceptions or log_exceptions                                                                                                                                                                                                                                   
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                       
    )                                                                                                                                                                                                                                                  
    ^                                                                                                                                               
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 558, in _handle_exception                                                                                          
    raise exception                                                       
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 526, in _async_step                                                                                                
    await getattr(self, handler)()                                                                                                                                                                                                                                                                      
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 764, in _async_call_service_step                                                                                   
    response_data = await self._async_run_long_action(                                      
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                      
    ...<9 lines>...                                                                         
    )                                                                                       
    ^                                                                                       
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 727, in _async_run_long_action                                                                                     
    return await long_task                                                                  
           ^^^^^^^^^^^^^^^                                                                  
  File "/usr/src/homeassistant/homeassistant/core.py", line 2799, in async_call             
    raise HomeAssistantError(                                                               
    ...<5 lines>...                                                                         
    )                                                                                       
homeassistant.exceptions.HomeAssistantError: Failed to process the returned action response data, expected a dictionary, but got <class 'NoneType'>                                      

That’s the script I’m using. and I can call it in the Developer tools, and see correct output

interface:
  - lan3:
      via: LLDP
      rid: "2"
      age: 14 days, 15:31:45
      chassis:
        mir4a:
          id:
            type: mac
....

My problems happen, when I try to get that data into the data attribute of a binary_sensor:

  template:
    - trigger:
        platform: time_pattern
        minutes: "/1"
      action:
        - service: script.get_lldp_from_openwrt
          data:
            target: binary_sensor.openwrt_hwsw
          response_variable: lldp_hwsw        
      binary_sensor:
        - name: OpenWrt HWSW UBUS LLDP Topo
          unique_id: openwrt_hwsw_ubus_lldp
          state: "{{ states('binary_sensor.openwrt_hwsw') }}"
          attributes:
            data: "{{ lldp_hwsw }}"

Edit: Oops, sorry, hadn’t spotted the small change. My bad

I changed your script, your script is the problem. Look at what I posted again please.

Sure you can. Go ahead and give it a try. As far as I can tell there are only two limitations:

  1. You obviously cannot overwrite a variable within the same variable action, as that would require two identical keys within the same block.

  2. You cannot define variables with the same name in trigger_variables and the “root” automation variables block.

This automation however works perfectly fine:

triggers: []
actions:
  - variables:
      test: Hello
  - variables:
      test: "{{ test }} World!"

When you create a variable test: Hello, that variable will forever remain Hello. You can attempt to overwrite it to your hearts content, the value in the variable will not change.

Same result in developer tools, and error log, and no change to binary_sensor.openwrt_hwsw_ubus_lldp_topo

You sound awfully sure about that but evidence would suggest otherwise.

Screenshot 2025-01-15 at 20.57.56

triggers: []
actions:
  - variables:
      test: "Yes"
  - variables:
      test: "{{ test }} this"
  - variables:
      test: "{{ test }} works"
  - variables:
      test: "{{ test }} perfectly"
  - variables:
      test: "{{ test }} fine"
  - variables:
      test: "{{ test }} thank"
  - variables:
      test: "{{ test }} you"
  - variables:
      test: "{{ test }} very"
  - variables:
      test: "{{ test }} much"

Can you show a trace please

Where other than homeassistant.log can I get more informative Tracebacks than the one I posted a few message up?