diff --git a/include/crm/msg_xml.h b/include/crm/msg_xml.h
index 673ae56beb..231d055bf7 100644
--- a/include/crm/msg_xml.h
+++ b/include/crm/msg_xml.h
@@ -1,293 +1,294 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_MSG_XML__H
 #  define PCMK__CRM_MSG_XML__H
 
 #  include <crm/common/xml.h>
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/msg_xml_compat.h>
 #endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /* This file defines constants for various XML syntax (mainly element and
  * attribute names).
  *
  * For consistency, new constants should start with "PCMK_", followed by:
  * * "XE" for XML element names
  * * "XA" for XML attribute names
  * * "OPT" for cluster option (property) names
  * * "META" for meta-attribute names
  * * "VALUE" for enumerated values for various options
  *
  * Old names that don't follow this policy should eventually be deprecated and
  * replaced with names that do.
  *
  * Symbols should be public if the user may specify them somewhere (especially
  * the CIB) or if they're part of a well-defined structure that a user may need
  * to parse. They should be internal if they're used only internally to
  * Pacemaker (such as daemon IPC/CPG message XML).
  *
  * Constants belong in the following locations:
  * * Public "XE" and "XA": msg_xml.h
  * * Internal "XE" and "XA": crm_internal.h
  * * Public "OPT", "META", and "VALUE": options.h
  * * Internal "OPT", "META", and "VALUE": options_internal.h
  *
  * For meta-attributes that can be specified as either XML attributes or nvpair
  * names, use "META" unless using both "XA" and "META" constants adds clarity.
  * An example is operation attributes, which can be specified either as
  * attributes of the PCMK_XE_OP element or as nvpairs in a meta-attribute set
  * beneath the PCMK_XE_OP element.
  */
 
 /*
  * XML elements
  */
 
 #define PCMK_XE_ACLS                        "acls"
 #define PCMK_XE_ALERT                       "alert"
 #define PCMK_XE_ALERTS                      "alerts"
 #define PCMK_XE_CIB                         "cib"
 #define PCMK_XE_CONFIGURATION               "configuration"
 #define PCMK_XE_CONSTRAINTS                 "constraints"
 #define PCMK_XE_CONTENT                     "content"
 #define PCMK_XE_CRM_CONFIG                  "crm_config"
 #define PCMK_XE_DATE_EXPRESSION             "date_expression"
 #define PCMK_XE_LONGDESC                    "longdesc"
 #define PCMK_XE_NODES                       "nodes"
 #define PCMK_XE_OP                          "op"
 #define PCMK_XE_OP_DEFAULTS                 "op_defaults"
 #define PCMK_XE_OPERATION                   "operation"
 #define PCMK_XE_OP_EXPRESSION               "op_expression"
 #define PCMK_XE_OPTION                      "option"
 #define PCMK_XE_RECIPIENT                   "recipient"
 #define PCMK_XE_RESOURCES                   "resources"
 #define PCMK_XE_ROLE                        "role"
 #define PCMK_XE_PARAMETER                   "parameter"
 #define PCMK_XE_PARAMETERS                  "parameters"
 #define PCMK_XE_RESOURCE_AGENT              "resource-agent"
 #define PCMK_XE_RSC_DEFAULTS                "rsc_defaults"
 #define PCMK_XE_RSC_EXPRESSION              "rsc_expression"
 #define PCMK_XE_SELECT                      "select"
 #define PCMK_XE_SELECT_ATTRIBUTES           "select_attributes"
+#define PCMK_XE_SELECT_FENCING              "select_fencing"
 #define PCMK_XE_SHORTDESC                   "shortdesc"
 #define PCMK_XE_STATUS                      "status"
 #define PCMK_XE_VERSION                     "version"
 
 
 /*
  * XML attributes
  */
 
 #define PCMK_XA_ADMIN_EPOCH                 "admin_epoch"
 #define PCMK_XA_ATTRIBUTE                   "attribute"
 #define PCMK_XA_BOOLEAN_OP                  "boolean-op"
 #define PCMK_XA_CIB_LAST_WRITTEN            "cib-last-written"
 #define PCMK_XA_CLASS                       "class"
 #define PCMK_XA_CRM_DEBUG_ORIGIN            "crm-debug-origin"
 #define PCMK_XA_CRM_FEATURE_SET             "crm_feature_set"
 #define PCMK_XA_CRM_TIMESTAMP               "crm-timestamp"
 #define PCMK_XA_DC_UUID                     "dc-uuid"
 #define PCMK_XA_DEFAULT                     "default"
 #define PCMK_XA_DESCRIPTION                 "description"
 #define PCMK_XA_DEVICES                     "devices"
 #define PCMK_XA_EPOCH                       "epoch"
 #define PCMK_XA_EXEC_TIME                   "exec-time"
 #define PCMK_XA_EXIT_REASON                 "exit-reason"
 #define PCMK_XA_FIRST                       "first"
 #define PCMK_XA_FIRST_ACTION                "first-action"
 #define PCMK_XA_FORMAT                      "format"
 #define PCMK_XA_HAVE_QUORUM                 "have-quorum"
 #define PCMK_XA_ID                          "id"
 #define PCMK_XA_ID_REF                      "id-ref"
 #define PCMK_XA_INDEX                       "index"
 #define PCMK_XA_INFLUENCE                   "influence"
 #define PCMK_XA_KIND                        "kind"
 #define PCMK_XA_LANG                        "lang"
 #define PCMK_XA_LAST_RC_CHANGE              "last-rc-change"
 #define PCMK_XA_LOSS_POLICY                 "loss-policy"
 #define PCMK_XA_NAME                        "name"
 #define PCMK_XA_NO_QUORUM_PANIC             "no-quorum-panic"
 #define PCMK_XA_NODE_ATTRIBUTE              "node-attribute"
 #define PCMK_XA_NUM_UPDATES                 "num_updates"
 #define PCMK_XA_OBJECT_TYPE                 "object-type"
 #define PCMK_XA_OP                          "op"
 #define PCMK_XA_OPERATION                   "operation"
 #define PCMK_XA_ORIGIN                      "origin"
 #define PCMK_XA_PATH                        "path"
 #define PCMK_XA_PROVIDER                    "provider"
 #define PCMK_XA_QUEUE_TIME                  "queue-time"
 #define PCMK_XA_REASON                      "reason"
 #define PCMK_XA_REFERENCE                   "reference"
 #define PCMK_XA_REQUEST                     "request"
 #define PCMK_XA_RESOURCE_DISCOVERY          "resource-discovery"
 #define PCMK_XA_RESULT                      "result"
 #define PCMK_XA_ROLE                        "role"
 #define PCMK_XA_RSC                         "rsc"
 #define PCMK_XA_RSC_PATTERN                 "rsc-pattern"
 #define PCMK_XA_RSC_ROLE                    "rsc-role"
 #define PCMK_XA_SCORE                       "score"
 #define PCMK_XA_SCORE_ATTRIBUTE             "score-attribute"
 #define PCMK_XA_SYMMETRICAL                 "symmetrical"
 #define PCMK_XA_TARGET                      "target"
 #define PCMK_XA_TARGET_ATTRIBUTE            "target-attribute"
 #define PCMK_XA_TARGET_PATTERN              "target-pattern"
 #define PCMK_XA_TARGET_VALUE                "target-value"
 #define PCMK_XA_TICKET                      "ticket"
 #define PCMK_XA_THEN                        "then"
 #define PCMK_XA_THEN_ACTION                 "then-action"
 #define PCMK_XA_TYPE                        "type"
 #define PCMK_XA_UNAME                       "uname"
 #define PCMK_XA_UPDATE_CLIENT               "update-client"
 #define PCMK_XA_UPDATE_ORIGIN               "update-origin"
 #define PCMK_XA_UPDATE_USER                 "update-user"
 #define PCMK_XA_VALIDATE_WITH               "validate-with"
 #define PCMK_XA_VALUE                       "value"
 #define PCMK_XA_VALUE_SOURCE                "value-source"
 #define PCMK_XA_VERSION                     "version"
 #define PCMK_XA_WITH_RSC                    "with-rsc"
 #define PCMK_XA_WITH_RSC_ROLE               "with-rsc-role"
 #define PCMK_XA_XPATH                       "xpath"
 
 
 /*
  * Older constants that don't follow current naming
  */
 
 #  ifndef T_CRM
 #    define T_CRM     "crmd"
 #  endif
 
 #  ifndef T_ATTRD
 #    define T_ATTRD     "attrd"
 #  endif
 
 #  define CIB_OPTIONS_FIRST "cib-bootstrap-options"
 
 #  define F_CRM_DATA			"crm_xml"
 
 /*---- Common tags/attrs */
 #  define XML_DIFF_MARKER		"__crm_diff_marker__"
 #  define XML_TAG_FAILED		"failed"
 
 #  define XML_TAG_OPTIONS		"options"
 
 /*---- top level tags/attrs */
 #  define XML_PING_ATTR_PACEMAKERDSTATE_INIT "init"
 #  define XML_PING_ATTR_PACEMAKERDSTATE_STARTINGDAEMONS "starting_daemons"
 #  define XML_PING_ATTR_PACEMAKERDSTATE_WAITPING "wait_for_ping"
 #  define XML_PING_ATTR_PACEMAKERDSTATE_RUNNING "running"
 #  define XML_PING_ATTR_PACEMAKERDSTATE_SHUTTINGDOWN "shutting_down"
 #  define XML_PING_ATTR_PACEMAKERDSTATE_SHUTDOWNCOMPLETE "shutdown_complete"
 #  define XML_PING_ATTR_PACEMAKERDSTATE_REMOTE "remote"
 
 #  define XML_FAIL_TAG_CIB		"failed_update"
 
 /*---- CIB specific tags/attrs */
 #  define XML_CIB_TAG_SECTION_ALL	"all"
-#  define XML_CIB_TAG_ALERT_FENCING     "select_fencing"
+#  define XML_CIB_TAG_ALERT_FENCING     PCMK_XE_SELECT_FENCING
 #  define XML_CIB_TAG_ALERT_NODES       "select_nodes"
 #  define XML_CIB_TAG_ALERT_RESOURCES   "select_resources"
 #  define XML_CIB_TAG_ALERT_ATTR        "attribute"
 
 #  define XML_CIB_TAG_STATE         	"node_state"
 #  define XML_CIB_TAG_NODE          	"node"
 #  define XML_CIB_TAG_NVPAIR        	"nvpair"
 
 #  define XML_CIB_TAG_PROPSET	   	"cluster_property_set"
 #  define XML_TAG_ATTR_SETS	   	"instance_attributes"
 #  define XML_TAG_META_SETS	   	"meta_attributes"
 #  define XML_TAG_ATTRS			"attributes"
 #  define XML_TAG_PARAM			"param"
 #  define XML_TAG_UTILIZATION		"utilization"
 
 #  define XML_TAG_RESOURCE_REF		"resource_ref"
 #  define XML_CIB_TAG_RESOURCE	  	"primitive"
 #  define XML_CIB_TAG_GROUP	  	"group"
 #  define XML_CIB_TAG_INCARNATION	"clone"
 #  define XML_CIB_TAG_CONTAINER		"bundle"
 
 #  define XML_CIB_TAG_RSC_TEMPLATE	"template"
 
 #  define XML_CIB_TAG_LRM		"lrm"
 #  define XML_LRM_TAG_RESOURCES     	"lrm_resources"
 #  define XML_LRM_TAG_RESOURCE     	"lrm_resource"
 #  define XML_LRM_TAG_RSC_OP		"lrm_rsc_op"
 
 #  define XML_NODE_IS_REMOTE    	"remote_node"
 #  define XML_NODE_IS_FENCED		"node_fenced"
 #  define XML_NODE_IS_MAINTENANCE   "node_in_maintenance"
 
 #  define XML_CIB_ATTR_SHUTDOWN       	"shutdown"
 
 #  define XML_TAG_GRAPH			"transition_graph"
 #  define XML_GRAPH_TAG_RSC_OP		"rsc_op"
 #  define XML_GRAPH_TAG_PSEUDO_EVENT	"pseudo_event"
 #  define XML_GRAPH_TAG_CRM_EVENT	"crm_event"
 #  define XML_GRAPH_TAG_DOWNED            "downed"
 #  define XML_GRAPH_TAG_MAINTENANCE       "maintenance"
 
 #  define XML_TAG_RULE			"rule"
 
 #  define XML_TAG_EXPRESSION		"expression"
 
 #  define XML_CONS_TAG_RSC_DEPEND	"rsc_colocation"
 #  define XML_CONS_TAG_RSC_ORDER	"rsc_order"
 #  define XML_CONS_TAG_RSC_LOCATION	"rsc_location"
 #  define XML_CONS_TAG_RSC_TICKET	"rsc_ticket"
 #  define XML_CONS_TAG_RSC_SET		"resource_set"
 
 #  define XML_NODE_ATTR_RSC_DISCOVERY   "resource-discovery-enabled"
 
 #  define XML_CIB_TAG_GENERATION_TUPPLE	"generation_tuple"
 
 #  define XML_TAG_TRANSIENT_NODEATTRS	"transient_attributes"
 
 #  define XML_ACL_TAG_USER		"acl_target"
 #  define XML_ACL_TAG_USERv1		"acl_user"
 #  define XML_ACL_TAG_GROUP		"acl_group"
 #  define XML_ACL_TAG_ROLE		"acl_role"
 #  define XML_ACL_TAG_PERMISSION	"acl_permission"
 #  define XML_ACL_TAG_ROLE_REFv1	"role_ref"
 #  define XML_ACL_TAG_READ		"read"
 #  define XML_ACL_TAG_WRITE		"write"
 #  define XML_ACL_TAG_DENY		"deny"
 
 #  define XML_CIB_TAG_TICKETS		"tickets"
 #  define XML_CIB_TAG_TICKET_STATE	"ticket_state"
 
 #  define XML_CIB_TAG_TAGS   		"tags"
 #  define XML_CIB_TAG_TAG   		"tag"
 #  define XML_CIB_TAG_OBJ_REF 		"obj_ref"
 
 #  define XML_TAG_FENCING_TOPOLOGY      "fencing-topology"
 #  define XML_TAG_FENCING_LEVEL         "fencing-level"
 
 #  define XML_TAG_DIFF                  "diff"
 #  define XML_DIFF_VERSION              PCMK_XE_VERSION
 #  define XML_DIFF_VSOURCE              "source"
 #  define XML_DIFF_VTARGET              "target"
 #  define XML_DIFF_CHANGE               "change"
 #  define XML_DIFF_LIST                 "change-list"
 #  define XML_DIFF_ATTR                 "change-attr"
 #  define XML_DIFF_RESULT               "change-result"
 #  define XML_DIFF_POSITION             "position"
 
 #  define ID(x) crm_element_value(x, PCMK_XA_ID)
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/lib/pengine/rules_alerts.c b/lib/pengine/rules_alerts.c
index fe744089a4..bde98a73d1 100644
--- a/lib/pengine/rules_alerts.c
+++ b/lib/pengine/rules_alerts.c
@@ -1,301 +1,301 @@
 /*
  * Copyright 2015-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 #include <crm/pengine/rules.h>
 #include <crm/common/alerts_internal.h>
 #include <crm/common/xml_internal.h>
 #include <crm/pengine/rules_internal.h>
 
 /*!
  * \internal
  * \brief Unpack an alert's or alert recipient's meta attributes
  *
  * \param[in,out] basenode     Alert or recipient XML
  * \param[in,out] entry        Where to store unpacked values
  * \param[in,out] max_timeout  Max timeout of all alerts and recipients thus far
  *
  * \return Standard Pacemaker return code
  */
 static int
 get_meta_attrs_from_cib(xmlNode *basenode, pcmk__alert_t *entry,
                         guint *max_timeout)
 {
     GHashTable *config_hash = pcmk__strkey_table(free, free);
     crm_time_t *now = crm_time_new(NULL);
     const char *value = NULL;
     int rc = pcmk_rc_ok;
 
     pe_unpack_nvpairs(basenode, basenode, XML_TAG_META_SETS, NULL, config_hash,
                       NULL, FALSE, now, NULL);
     crm_time_free(now);
 
     value = g_hash_table_lookup(config_hash, PCMK_META_ENABLED);
     if ((value != NULL) && !crm_is_true(value)) {
         // No need to continue unpacking
         rc = pcmk_rc_disabled;
         goto done;
     }
 
     value = g_hash_table_lookup(config_hash, PCMK_META_TIMEOUT);
     if (value) {
         entry->timeout = crm_get_msec(value);
         if (entry->timeout <= 0) {
             if (entry->timeout == 0) {
                 crm_trace("Alert %s uses default timeout of %dmsec",
                           entry->id, PCMK__ALERT_DEFAULT_TIMEOUT_MS);
             } else {
                 pcmk__config_warn("Alert %s has invalid timeout value '%s', "
                                   "using default (%d ms)",
                                   entry->id, value,
                                   PCMK__ALERT_DEFAULT_TIMEOUT_MS);
             }
             entry->timeout = PCMK__ALERT_DEFAULT_TIMEOUT_MS;
         } else {
             crm_trace("Alert %s uses timeout of %dmsec",
                       entry->id, entry->timeout);
         }
         if (entry->timeout > *max_timeout) {
             *max_timeout = entry->timeout;
         }
     }
     value = g_hash_table_lookup(config_hash, PCMK_META_TIMESTAMP_FORMAT);
     if (value) {
         /* hard to do any checks here as merely anything can
          * can be a valid time-format-string
          */
         entry->tstamp_format = strdup(value);
         crm_trace("Alert %s uses timestamp format '%s'",
                   entry->id, entry->tstamp_format);
     }
 
 done:
     g_hash_table_destroy(config_hash);
     return rc;
 }
 
 static void
 get_envvars_from_cib(xmlNode *basenode, pcmk__alert_t *entry)
 {
     xmlNode *child;
 
     if ((basenode == NULL) || (entry == NULL)) {
         return;
     }
 
     child = first_named_child(basenode, XML_TAG_ATTR_SETS);
     if (child == NULL) {
         return;
     }
 
     if (entry->envvars == NULL) {
         entry->envvars = pcmk__strkey_table(free, free);
     }
 
     for (child = first_named_child(child, XML_CIB_TAG_NVPAIR); child != NULL;
          child = crm_next_same_xml(child)) {
 
         const char *name = crm_element_value(child, PCMK_XA_NAME);
         const char *value = crm_element_value(child, PCMK_XA_VALUE);
 
         if (value == NULL) {
             value = "";
         }
         g_hash_table_insert(entry->envvars, strdup(name), strdup(value));
         crm_trace("Alert %s: added environment variable %s='%s'",
                   entry->id, name, value);
     }
 }
 
 static void
 unpack_alert_filter(xmlNode *basenode, pcmk__alert_t *entry)
 {
     xmlNode *select = first_named_child(basenode, PCMK_XE_SELECT);
     xmlNode *event_type = NULL;
     uint32_t flags = pcmk__alert_none;
 
     for (event_type = pcmk__xe_first_child(select); event_type != NULL;
          event_type = pcmk__xe_next(event_type)) {
 
-        if (pcmk__xe_is(event_type, XML_CIB_TAG_ALERT_FENCING)) {
+        if (pcmk__xe_is(event_type, PCMK_XE_SELECT_FENCING)) {
             flags |= pcmk__alert_fencing;
 
         } else if (pcmk__xe_is(event_type, XML_CIB_TAG_ALERT_NODES)) {
             flags |= pcmk__alert_node;
 
         } else if (pcmk__xe_is(event_type, XML_CIB_TAG_ALERT_RESOURCES)) {
             flags |= pcmk__alert_resource;
 
         } else if (pcmk__xe_is(event_type, PCMK_XE_SELECT_ATTRIBUTES)) {
             xmlNode *attr;
             const char *attr_name;
             int nattrs = 0;
 
             flags |= pcmk__alert_attribute;
             for (attr = first_named_child(event_type, XML_CIB_TAG_ALERT_ATTR);
                  attr != NULL;
                  attr = crm_next_same_xml(attr)) {
 
                 attr_name = crm_element_value(attr, PCMK_XA_NAME);
                 if (attr_name) {
                     if (nattrs == 0) {
                         g_strfreev(entry->select_attribute_name);
                         entry->select_attribute_name = NULL;
                     }
                     ++nattrs;
                     entry->select_attribute_name = pcmk__realloc(entry->select_attribute_name,
                                                                  (nattrs + 1) * sizeof(char*));
                     entry->select_attribute_name[nattrs - 1] = strdup(attr_name);
                     entry->select_attribute_name[nattrs] = NULL;
                 }
             }
         }
     }
 
     if (flags != pcmk__alert_none) {
         entry->flags = flags;
         crm_debug("Alert %s receives events: attributes:%s%s%s%s",
                   entry->id,
                   (pcmk_is_set(flags, pcmk__alert_attribute)?
                    (entry->select_attribute_name? "some" : "all") : "none"),
                   (pcmk_is_set(flags, pcmk__alert_fencing)? " fencing" : ""),
                   (pcmk_is_set(flags, pcmk__alert_node)? " nodes" : ""),
                   (pcmk_is_set(flags, pcmk__alert_resource)? " resources" : ""));
     }
 }
 
 /*!
  * \internal
  * \brief Unpack an alert or an alert recipient
  *
  * \param[in,out] alert        Alert or recipient XML
  * \param[in,out] entry        Where to store unpacked values
  * \param[in,out] max_timeout  Max timeout of all alerts and recipients thus far
  *
  * \return Standard Pacemaker return code
  */
 static int
 unpack_alert(xmlNode *alert, pcmk__alert_t *entry, guint *max_timeout)
 {
     int rc = pcmk_rc_ok;
 
     get_envvars_from_cib(alert, entry);
     rc = get_meta_attrs_from_cib(alert, entry, max_timeout);
     if (rc == pcmk_rc_ok) {
         unpack_alert_filter(alert, entry);
     }
     return rc;
 }
 
 /*!
  * \internal
  * \brief Unpack a CIB alerts section
  *
  * \param[in] alerts  XML of alerts section
  *
  * \return  List of unpacked alert entries
  *
  * \note Unlike most unpack functions, this is not used by the scheduler itself,
  *       but is supplied for use by daemons that need to send alerts.
  */
 GList *
 pe_unpack_alerts(const xmlNode *alerts)
 {
     xmlNode *alert;
     pcmk__alert_t *entry;
     guint max_timeout = 0;
     GList *alert_list = NULL;
 
     if (alerts == NULL) {
         return alert_list;
     }
 
     for (alert = first_named_child(alerts, PCMK_XE_ALERT); alert != NULL;
          alert = crm_next_same_xml(alert)) {
 
         xmlNode *recipient;
         int recipients = 0;
         const char *alert_id = ID(alert);
         const char *alert_path = crm_element_value(alert, PCMK_XA_PATH);
 
         /* The schema should enforce this, but to be safe ... */
         if (alert_id == NULL) {
             pcmk__config_warn("Ignoring invalid alert without " PCMK_XA_ID);
             crm_log_xml_info(alert, "missing-id");
             continue;
         }
         if (alert_path == NULL) {
             pcmk__config_warn("Ignoring alert %s: No " PCMK_XA_PATH, alert_id);
             continue;
         }
 
         entry = pcmk__alert_new(alert_id, alert_path);
 
         if (unpack_alert(alert, entry, &max_timeout) != pcmk_rc_ok) {
             // Don't allow recipients to override if entire alert is disabled
             crm_debug("Alert %s is disabled", entry->id);
             pcmk__free_alert(entry);
             continue;
         }
 
         if (entry->tstamp_format == NULL) {
             entry->tstamp_format = strdup(PCMK__ALERT_DEFAULT_TSTAMP_FORMAT);
         }
 
         crm_debug("Alert %s: path=%s timeout=%dms tstamp-format='%s' %u vars",
                   entry->id, entry->path, entry->timeout, entry->tstamp_format,
                   (entry->envvars? g_hash_table_size(entry->envvars) : 0));
 
         for (recipient = first_named_child(alert, PCMK_XE_RECIPIENT);
              recipient != NULL; recipient = crm_next_same_xml(recipient)) {
 
             pcmk__alert_t *recipient_entry = pcmk__dup_alert(entry);
 
             recipients++;
             recipient_entry->recipient = crm_element_value_copy(recipient,
                                                                 PCMK_XA_VALUE);
 
             if (unpack_alert(recipient, recipient_entry,
                              &max_timeout) != pcmk_rc_ok) {
                 crm_debug("Alert %s: recipient %s is disabled",
                           entry->id, recipient_entry->id);
                 pcmk__free_alert(recipient_entry);
                 continue;
             }
             alert_list = g_list_prepend(alert_list, recipient_entry);
             crm_debug("Alert %s has recipient %s with value %s and %d envvars",
                       entry->id, ID(recipient), recipient_entry->recipient,
                       (recipient_entry->envvars?
                        g_hash_table_size(recipient_entry->envvars) : 0));
         }
 
         if (recipients == 0) {
             alert_list = g_list_prepend(alert_list, entry);
         } else {
             pcmk__free_alert(entry);
         }
     }
     return alert_list;
 }
 
 /*!
  * \internal
  * \brief Free an alert list generated by pe_unpack_alerts()
  *
  * \param[in,out] alert_list  Alert list to free
  */
 void
 pe_free_alert_list(GList *alert_list)
 {
     if (alert_list) {
         g_list_free_full(alert_list, (GDestroyNotify) pcmk__free_alert);
     }
 }