Repository navigation
Description
Component
SQL collection scripts
Performance Monitor Version
3.2.0
SQL Server Version
Microsoft SQL Server 2025 (RTM-CU7) (KB5096981) - 17.0.4065.4 (X64) Jul 8 2026 23:26:08 Copyright (C) 2025 Microsoft Corporation Enterprise Developer Edition (64-bit) on Linux (Ubuntu 24.04.4 LTS)
Windows Version
N/A - reproduced via Docker - the bug is independent of the client/host OS
Describe the Bug
The report.trace_flag_changes view contains a CASE expression that compares previous_status and status (both bit columns from config.trace_flags_history) against nvarchar literals:
WHEN rc.previous_status = N'OFF' AND rc.status = N'ON' THEN ...
WHEN rc.previous_status = N'ON' AND rc.status = N'OFF' THEN ...SQL Server resolves the type mismatch by converting the string literal to bit. The error always names 'OFF' here likely because it's the first literal SQL Server attempts to fold
Conversion failed when converting the nvarchar value 'OFF' to data type bit.
The view filters to change_number > 1 (rows with a non-NULL previous_status), so the first INSERT into the history table never triggers the error. The view breaks the moment a second row exists for any trace flag - i.e. after any toggle is recorded.
Steps to Reproduce
docker pull mcr.microsoft.com/mssql/server:2022-latest
docker run -e ACCEPT_EULA=Y -e MSSQL_SA_PASSWORD='HopeThisIsGoodEnough123!' \
--name sqltest -p 1433:1433 -d mcr.microsoft.com/mssql/server:2022-latest
# brief pause for sql service to start up
sleep 15Create a minimal history table in tempdb (not a #temp table - each docker exec sqlcmd -Q call is its own connection/session, so a session-scoped temp table wouldn't survive between steps) and insert two rows (initial + toggle):
docker exec -it sqltest /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P 'HopeThisIsGoodEnough123!' -C -Q \
"CREATE TABLE tempdb.dbo.history (
collection_time datetime2,
trace_flag int,
status bit,
is_global bit,
is_session bit
);
/* Initial capture: TF 1222 off */
INSERT tempdb.dbo.history VALUES ('2026-07-24 00:00:00', 1222, 0, 1, 0);
/* Second capture: TF 1222 toggled on */
INSERT tempdb.dbo.history VALUES ('2026-07-24 01:00:00', 1222, 1, 1, 0);
SELECT trace_flag, status, is_global, collection_time FROM tempdb.dbo.history;"Expected: two rows, status 0 then 1.
Run the CASE expression and observe the error:
docker exec -it sqltest /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P 'HopeThisIsGoodEnough123!' -C -Q \
"WITH ranked AS (
SELECT
status,
is_global,
is_session,
trace_flag,
previous_status =
LAG(status, 1) OVER (PARTITION BY trace_flag, is_global ORDER BY collection_time),
change_number =
ROW_NUMBER() OVER (PARTITION BY trace_flag, is_global ORDER BY collection_time)
FROM tempdb.dbo.history
)
SELECT
trace_flag,
change_description =
CASE
WHEN previous_status = N'OFF' AND status = N'ON'
THEN N'Trace flag ' + CONVERT(nvarchar(10), trace_flag) + N' ENABLED'
WHEN previous_status = N'ON' AND status = N'OFF'
THEN N'Trace flag ' + CONVERT(nvarchar(10), trace_flag) + N' DISABLED'
ELSE N'Status unchanged'
END
FROM ranked
WHERE change_number > 1;"Compare against the fixed expression (replace nvarchar literals with 0 and 1):
docker exec -it sqltest /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P 'HopeThisIsGoodEnough123!' -C -Q \
"WITH ranked AS (
SELECT
status,
is_global,
is_session,
trace_flag,
previous_status =
LAG(status, 1) OVER (PARTITION BY trace_flag, is_global ORDER BY collection_time),
change_number =
ROW_NUMBER() OVER (PARTITION BY trace_flag, is_global ORDER BY collection_time)
FROM tempdb.dbo.history
)
SELECT
trace_flag,
change_description =
CASE
WHEN previous_status = 0 AND status = 1
THEN N'Trace flag ' + CONVERT(nvarchar(10), trace_flag) + N' ENABLED'
WHEN previous_status = 1 AND status = 0
THEN N'Trace flag ' + CONVERT(nvarchar(10), trace_flag) + N' DISABLED'
ELSE N'Status unchanged'
END
FROM ranked
WHERE change_number > 1;"Cleanup:
docker rm -f sqltestExpected Behavior
The view should return one row describing the toggle:
trace_flag change_description
----------- ---------------------------------
1222 Trace flag 1222 ENABLED
Actual Behavior
Msg 245, Level 16, State 1, Server ...
Conversion failed when converting the nvarchar value 'OFF' to data type bit.
Any query against report.trace_flag_changes fails outright once a second history row exists for any trace flag - i.e. after the first toggle is recorded.
Error Messages / Log Output
Msg 245, Level 16, State 1, Server ...
Conversion failed when converting the nvarchar value 'OFF' to data type bit.
Screenshots
NA
Additional Context
Fix: compare previous_status/status against 0/1 instead of N'OFF'/N'ON', matching the underlying bit type. Applied as a two-line change to the CASE expression in install/47_create_reporting_views.sql (report.trace_flag_changes view definition), idempotent via CREATE OR ALTER VIEW.
Activity
argpna commentedon Jul 24, 2026
P.S. Hey Erik - sorry for the barrage of bug fix issues today, figured I owed you some context. I built a downstream companion repo that plugs the monitoring queries into Grafana, and chasing that down tripped a bunch of bugs over the past few weeks, so I'm finally getting around to posting them.
Repo's here if you want to poke around: https://github.com/argpna/eriksperfmon (called it "erik's perfmon" - hope that's fine by you 😄 ).
Screenshots of the Grafana dashboards are here: https://argpna.github.io/eriksperfmon-demo/ - covers both the main perfmon dashboards and the finops ones.
It auto-discovers wherever the PerformanceMonitor database lives in an environment and wires up the Grafana MSSQL datasource for it, plus an installer/upgrader for PerformanceMonitor releases itself - all Ansible, scales to however many servers you throw at it. There's also a local Docker setup so anyone can click through a real Grafana experience without a real environment (synthetic workloads feed a few SQL containers so data actually flows).
The Grafana dashboards aren't meant as a full replacement for the WPF dashboard - there's still a handful of things missing compared to it, all called out in the downstream repo's docs.
... BTW, I did find a few more issues building it out, too - I'll post those over the next few days.
erikdarlingdata commentedon Jul 24, 2026
@argpna all good with me. I played around with Grafana a bit when I first started building this stuff, but didn't end up going that direction because not everyone is set up to use it immediately. Anyway, glad you're finding some of this stuff useful. Happy to get any bug fixes you find in.
argpna commentedon Jul 24, 2026
Awesome, thanks!
erikdarlingdata commentedon Jul 25, 2026
Fixed and merged to
dev— thanks for the fix, @argpna.The view compared the bit-typed
previous_status/statuscolumns againstN'OFF'/N'ON'literals. Bit outranks nvarchar in type precedence, so SQL Server converted the literal to bit and the view failed the moment a toggle row flowed through it. It now compares0/1.Fix: PR #1637, merge
4f2b7ced. Ships in the next release.Dashboard: read trace-flag status bits as bits, format ON/OFF reader-…
CI: execute every report view against seeded rows (erikdarlingdata#1669)