Applications Systems

Alert variable ${N=SwisEntity;M=ComponentAlert.StatusOrErrorDescription} is resolving to a raw resource token '@{R=APM.Strings;K=APMSQLDATA_ComponentStatusInformationPrefix;E=SQL}' instead of human‑readable error message in SAM

This article addresses an issue where the StatusOrErrorDescription component alert variable on Windows Service Monitor components resolves to a resource key string (@{R=APM.Strings;K=APMSQLDATA_ComponentStatusInformationPrefix;E=SQL}) instead of a human‑readable status or error message when used in alert actions such as email. The same variable works correctly for other monitor types, such as Windows Event Log Monitor.

First published date

2/25/2026 8:14 PM

Last published date

2/25/2026 9:36 PM

Overview

When configuring or simulating an email action for a SAM alert on a Windows Service Monitor or Powershell Script component monitor, the following variable:

${N=SwisEntity;M=ComponentAlert.StatusOrErrorDescription}

resolves to a raw resource token, for example:

@{R=APM.Strings;K=APMSQLDATA_ComponentStatusInformationPrefix;E=SQL}

instead of a descriptive status or error message.

The same variable resolves correctly (human‑readable) when used on other component types such as Windows Event Log Monitor.

Product section

Server Application Monitor

Cause

The behavior is caused by how the StatusOrErrorDescription value is built in the database function [dbo].[apm_GetComponentStatusErrorDescription] for certain evidence types

Resolution

Resolution:

Note:

The fix for this issue was included in the 2025.2 or later release. Upgrade to 2025.2 or later version to ensure the issue is resolved. 

If you are unable to upgrade to this version, you can try the below workarounds:

Option1: Interim database workaround

  • Stop SolarWinds Platform services

    • Diable HA globally ig there's any
    • On the main polling engine, stop all SolarWinds services

  • In SQL Server Management Studio (SSMS), connect to the SolarWinds Platform database. Run the SQL script below:

Please coordinate this with your DBA and ensure that you have backup of database before doing manual changes.

-- Scripts are not supported under any SolarWinds support program or service.
-- Scripts are provided AS IS without warranty of any kind. SolarWinds further
-- disclaims all warranties including, without limitation, any implied warranties
-- of merchantability or of fitness for a particular purpose. The risk arising
-- out of the use or performance of the scripts and documentation stays with you.
-- In no event shall SolarWinds or anyone else involved in the creation,
-- production, or delivery of the scripts be liable for any damages whatsoever
-- (including, without limitation, damages for loss of business profits, business
-- interruption, loss of business information, or other pecuniary loss) arising
-- out of the use of or inability to use the scripts or documentation.

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[apm_GetComponentStatusErrorDescription]') AND xtype in (N'FN', N'IF', N'TF'))
	DROP FUNCTION [dbo].[apm_GetComponentStatusErrorDescription]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[apm_GetComponentStatusErrorDescription]
(
	@Id int,
	@EvidenceType int
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
	DECLARE @errorDesc NVARCHAR(MAX);
	SET @errorDesc = NULL;

	 -- port evidence
	IF (@EvidenceType = 2)
		BEGIN
		   SELECT @errorDesc = ec.ErrorDescription + coalesce(' ' + sc.StatusDescription, '') + coalesce(' ' + ccs.ErrorMessage, '')
			 FROM APM_CurrentComponentStatus ccs WITH (NOLOCK)
			 INNER JOIN APM_PortEvidence_CS_cur pe WITH (NOLOCK) 
					 ON ccs.ComponentStatusID = pe.ComponentStatusID
			 LEFT JOIN APM_ComponentError_CS_cur ce WITH (NOLOCK) 
					ON pe.ComponentID = ce.ComponentID AND pe.[Timestamp] = ce.[Timestamp]
			 LEFT JOIN APM_ErrorCode ec WITH (NOLOCK) 
					ON ccs.ErrorCode = ec.ID
			 LEFT JOIN APM_StatusCode sc WITH (NOLOCK) 
					ON ce.StatusCode = sc.ID AND ce.StatusCodeType = sc.StatusCodeTypeID
		   WHERE ccs.ComponentID = @Id
		END
		
	 -- process or dynamic
	ELSE IF (@EvidenceType IN (1, 3))
		BEGIN
		   IF EXISTS (SELECT * FROM APM_CurrentComponentStatus WITH (NOLOCK) WHERE ComponentID = @Id AND ErrorCode = 0)
				BEGIN
				   SELECT @errorDesc = REPLACE(N'@{R=APM.Strings;K=APMSQLDATA_ComponentStatusInformationPrefix;E=SQL}','{0}',LOWER(asm.DisplayName)) + coalesce(' ' + ccs.ErrorMessage, '')
					 FROM APM_CurrentComponentStatus ccs WITH (NOLOCK) 
					 LEFT JOIN dbo.APM_StatusMetadata asm WITH (NOLOCK) 
							ON asm.ApmStatusValue = ISNULL(ccs.Availability, 0)
				   WHERE ccs.ComponentID = @Id AND ErrorCode = 0
				END
			ELSE
				BEGIN
				   SELECT @errorDesc = ec.ErrorDescription + coalesce(' ' + ccs.ErrorMessage, '')
					 FROM APM_CurrentComponentStatus ccs WITH (NOLOCK)
					 LEFT JOIN APM_ErrorCode ec WITH (NOLOCK) 
							ON ccs.ErrorCode = ec.ID
				   WHERE ccs.ComponentID = @Id  
				END
		END 
	
	-- other black box components
	IF (@errorDesc IS NULL)
		BEGIN
		   SELECT @errorDesc = asm.DisplayName 
		     FROM dbo.APM_CurrentComponentStatus ccs WITH (NOLOCK)
		     LEFT JOIN dbo.APM_StatusMetadata asm WITH (NOLOCK) 
					ON asm.ApmStatusValue = ISNULL(ccs.Availability, 0)
		   WHERE ccs.ComponentID = @Id
		END
		
	return @errorDesc;

END
GO

 

  • Start all SolarWinds services on the main polling engine again.
  • Validate
    • Re‑run Simulate This Alert on an affected Windows Service Monitor component.

    • Confirm that ${N=SwisEntity;M=ComponentAlert.StatusOrErrorDescription} now shows a readable status/error description instead of @{R=APM.Strings;K=APMSQLDATA_ComponentStatusInformationPrefix;E=SQL}.

Option2: Use different Alert Variables:

Use combinations of these variables in the alert email body:

 

  • Component status:
${N=SwisEntity;M=Component.Status}
  • Component message
${N=SwisEntity;M=ComponentAlert.ComponentMessage}