Zigbee2mqtt configuration.yaml Error

Tags: #<Tag:0x00007f3288882680> #<Tag:0x00007f3288882590>

Hello, I’m trying to configure zigbee2mqtt, but when I check my configuration.yaml from within the HA UI, it gives me the error
expected a dictionary for dictionary value @ data[‘packages’][‘sensor’]

Here’s my config:
configuration.yaml homeassistant section:

homeassistant:
  packages: !include_dir_merge_named packages/

packages/zigbee2mqtt.yaml

# Input select for Zigbee2MQTT debug level
input_select:
  zigbee2mqtt_log_level:
    name: Zigbee2MQTT Log Level
    options:
      - debug
      - info
      - warn
      - error
    initial: info
    icon: mdi:format-list-bulleted

# Input number for joining time remaining (in minutes)
input_number:
  zigbee2mqtt_join_minutes:
    name: "Zigbee2MQTT join minutes"
    initial: 2
    min: 1
    max: 5
    step: 1
    mode: slider
    
# Input text to input Zigbee2MQTT friendly_name for scripts
input_text:
  zigbee2mqtt_old_name:
    name: Zigbee2MQTT Old Name
    initial: ""
  zigbee2mqtt_new_name:
    name: Zigbee2MQTT New Name
    initial: ""
  zigbee2mqtt_remove:
    name: Zigbee2MQTT Remove
    initial: ""

# Scripts for renaming & removing devices
script:
  zigbee2mqtt_rename:
    alias: Zigbee2MQTT Rename
    sequence:
      service: mqtt.publish
      data_template:
        topic: zigbee2mqtt/bridge/config/rename
        payload_template: >-
          {
            "old": "{{ states.input_text.zigbee2mqtt_old_name.state | string }}",
            "new": "{{ states.input_text.zigbee2mqtt_new_name.state | string }}"
          }
  zigbee2mqtt_remove:
    alias: Zigbee2MQTT Remove
    sequence:
      service: mqtt.publish
      data_template:
        topic: zigbee2mqtt/bridge/config/remove
        payload_template: "{{ states.input_text.zigbee2mqtt_remove.state | string }}"

# Timer for joining time remaining
timer:
  zigbee_permit_join:
    name: Time remaining

sensor:
  # Sensor for monitoring the bridge state
  - platform: mqtt
    name: Zigbee2MQTT Bridge state
    state_topic: "zigbee2mqtt/bridge/state"
    icon: mdi:router-wireless
  # Sensor for Showing the Zigbee2MQTT Version
  - platform: mqtt
    name: Zigbee2MQTT Version
    state_topic: "zigbee2mqtt/bridge/config"
    value_template: "{{ value_json.version }}"
    icon: mdi:zigbee
  # Sensor for Showing the Coordinator Version
  - platform: mqtt
    name: Coordinator Version
    state_topic: "zigbee2mqtt/bridge/config"
    value_template: "{{ value_json.coordinator }}"
    icon: mdi:chip

# Switch for enabling joining
switch:
  - platform: mqtt
    name: "Zigbee2MQTT Main join"
    state_topic: "zigbee2mqtt/bridge/config/permit_join"
    command_topic: "zigbee2mqtt/bridge/config/permit_join"
    payload_on: "true"
    payload_off: "false"

automation:
  # Automation for sending MQTT message on input select change
  - id: zigbee2mqtt_log_level
    alias: Zigbee2MQTT log level
    initial_state: "on"
    trigger:
      platform: state
      entity_id: input_select.zigbee2mqtt_log_level
    action:
      - service: mqtt.publish
        data:
          payload_template: "{{ states('input_select.zigbee2mqtt_log_level') }}"
          topic: zigbee2mqtt/bridge/config/log_level
  # Automation to start timer when enable join is turned on
  - id: zigbee_join_enabled
    alias: Zigbee Join Enabled
    trigger:
      platform: state
      entity_id: switch.zigbee2mqtt_main_join
      to: "on"
    action:
      service: timer.start
      entity_id: timer.zigbee_permit_join
      data_template:
        duration: "{{ '00:0%i:00' % (states('input_number.zigbee2mqtt_join_minutes') | int ) }}"
  # Automation to stop timer when switch turned off and turn off switch when timer finished
  - id: zigbee_join_disabled
    alias: Zigbee Join Disabled
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.zigbee_permit_join
      - platform: state
        entity_id: switch.zigbee2mqtt_main_join
        to: "off"
    action:
      - service: timer.cancel
        data:
          entity_id: timer.zigbee_permit_join
      - service: switch.turn_off
        entity_id: switch.zigbee2mqtt_main_join
  - id: "zigbee2mqtt_create_notification_on_successfull_interview"
    alias: Zigbee Device Joined Notification
    trigger:
      platform: mqtt
      topic: 'zigbee2mqtt/bridge/log'
    condition:
      condition: template
      value_template: '{{trigger.payload_json.type == "pairing" and trigger.payload_json.message == "interview_successful"}}'
    action:
      - service: persistent_notification.create
        data_template:
          title: Device joined the Zigbee2MQTT network
          message: "Name: {{trigger.payload_json.meta.friendly_name}},
                    Vendor: {{trigger.payload_json.meta.vendor}},
                    Description: {{trigger.payload_json.meta.description}}"

Instantly found the error. I forgot to enclose everything within zigbee2mqtt.yaml in a zigbee2mqtt: section.

That’s not the solution and you’re going to find yourself in all sorts of complicated situations using packages like that.

Change your zigbee2mqtt.yaml back to how it was when you pasted it and change the line in configuration.yaml to

homeassistant:
  packages: !include_dir_named packages/

(without the _merge)

Why? Can you elaborate a bit further?

Because zigbee2mqtt: isn’t a homeassistant key.

You’re generating packages using the wrong include method, so you’re having to ‘hack’ a workaround which is to name the package by generating your own unique package name inside the package, whereas if you included it correctly the package name is generated automatically from the filename (which is unique by its nature, as you cannot have 2 identically named files in any directory).

This is the kind of ‘hack’ that you’ll overlook at some point in the future and something won’t work as you expect, and then when you come here for help nobody will know that you’re using a hack so all the fixes you’re offered won’t work.

Basically, you can configure your homeassistant however you want, but sticking to ‘best practice’ and not hacking around it from the start is a far more reliable way to keep your system stable.