If you use SESSION_CONTEXT() in any query that can run with parallelism, you may be getting wrong results right now and not know it. This is not new. It has been a documented known issue since January 2022. It shipped unfixed in SQL Server 2019, 2022, and 2025 — and as of 2025 CU2 (February 12, 2026), it is still not resolved.
This is easy to miss. It's buried in the Known Issues section of CU release notes, and the symptoms — wrong results or dump files — do not obviously point back to SESSION_CONTEXT.
What the Bug Does
Queries that call the built-in SESSION_CONTEXT function can return incorrect results when they execute with parallel plans. The issue is how SESSION_CONTEXT interacts with parallel execution threads — specifically when the session is reset for connection pool reuse. Parallel threads read the session context, but under certain conditions the value is not properly propagated across all threads. Some threads see it, others don't. The query completes without error. The results are just wrong.
Microsoft's own SESSION_CONTEXT documentation describes it this way:
Known Issues: An Access Violation (AV) exception might occur with the SESSION_CONTEXT function under certain conditions. You might encounter AV exceptions or wrong results when the SESSION_CONTEXT function runs within a parallel execution plan when the session is reset for reuse. Date discovered: January 2022 Status: Has workaround Date resolved: (blank)
There are two failure modes:
| Failure | Cause |
|---|---|
| Wrong results | Original bug. Parallel threads do not all receive the session context value. |
| Access violation dumps | The fix for wrong results (introduced in 2019 CU14) causes AV dump files when the session is reset for reuse. |
You either get wrong data or crash dumps. Pick your poison.
Why This Is Dangerous
SESSION_CONTEXT is not obscure. It is Microsoft's recommended mechanism for passing application context into SQL Server. If your application calls sp_set_session_context to set a TenantID or any other value — and your queries filter on that value — you are potentially at risk.
Common patterns that use SESSION_CONTEXT:
Row-Level Security (RLS) — security predicates that filter rows by SESSION_CONTEXT(N'TenantID')
Multi-tenant data isolation — WHERE clauses filtering on session-injected tenant or org identifiers
Audit context — triggers or views that stamp SESSION_CONTEXT(N'UserID') into audit columns
The danger is that this failure is silent. No error message. No warning. The query completes successfully. It just returns rows that belong to another user — or excludes rows that should have been included. You would only catch it if you validated the result set, and most applications do not validate what the database returns from a SELECT.
Where It Lives
This is listed as a known issue on every cumulative update from SQL Server 2019 CU14 (November 2021) through SQL Server 2025 CU2 (February 2026). Three major versions. Over three years.
| Version | CU Range | Status |
|---|---|---|
| SQL Server 2019 | CU14 – CU31 | Known issue with workaround |
| SQL Server 2022 | CU1 – CU23 | Known issue with workaround |
| SQL Server 2025 | RTM – CU2 | Known issue with workaround |
Sources: SQL Server 2025 CU2 (KB5075211), SQL Server 2022 CU23 (KB5078297), SQL Server 2019 CU14.
The Workaround
Microsoft provides two trace flags:
| Trace Flag | What It Does |
|---|---|
| 11042 | Forces queries using SESSION_CONTEXT to run serially — no parallelism |
| 9432 | Disables the CU14 fix that causes access violation dump files |
TF 11042 is the one you want for most environments. It forces serial execution for any query that references SESSION_CONTEXT, which eliminates the parallel thread propagation problem entirely. The trade-off is performance — those queries lose parallelism. For many RLS and tenant-filter patterns, the queries are lightweight enough that serial execution will not matter.
TF 9432 disables the original fix, meaning you go back to pre-CU14 behavior: no access violations, but the wrong-results bug returns. Only use this if you are experiencing dump files and need to stop them immediately.
To enable globally:
-- Enable at runtime (survives until restart) DBCC TRACEON(11042, -1); GO -- Verify DBCC TRACESTATUS(11042, 9432); GO
For persistence across restarts, add -T11042 to your SQL Server startup parameters.
Are You Exposed?
This query checks whether SESSION_CONTEXT appears in any cached plan that has executed with parallelism:
SELECT
qs.plan_handle,
qs.sql_handle,
qs.execution_count,
qs.max_dop,
SUBSTRING(st.text,
(qs.statement_start_offset / 2) + 1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE qs.statement_end_offset
END - qs.statement_start_offset) / 2) + 1) AS query_text
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
WHERE st.text LIKE '%SESSION_CONTEXT%'
AND qs.max_dop > 1
ORDER BY qs.execution_count DESC;
If that returns rows, you have queries using SESSION_CONTEXT that have executed with parallel plans. You have a problem.
Also check whether the trace flags are already enabled — if someone on your team found this before you did, you will want to know:
DBCC TRACESTATUS(11042, 9432); GO
Bottom Line
SESSION_CONTEXT is Microsoft's recommended mechanism for passing application context into SQL Server. That recommendation has had a known parallel execution bug since January 2022. The original bug returns wrong results silently. A fix shipped in November 2021 (SQL Server 2019 CU14) stopped the wrong results but introduced access violation dump files. Neither problem has been fully resolved. The workaround is TF 11042, which forces affected queries to run serially.
Run the diagnostic query. If you get rows back, enable TF 11042. The performance cost of serial execution is almost always cheaper than the cost of returning inaccurate data.
More to Read:
Microsoft: SESSION_CONTEXT Known Issues
Microsoft: SQL Server 2025 CU2 (KB5075211)
Microsoft: KB5008114 — SESSION_CONTEXT Returns Wrong Results in Parallel Plans
Niko Neugebauer: SQL Server 2019 — Session Context & Parallel Plans
Hi Rebecca, “buried” is overselling it a little. We have to put these things somewhere, and in this particular case it’s the order in which they were reported to the docs team. If you can help us to improve the Known issues article, you’re welcome to submit a pull request.
ReplyDeleteFair enough — 'buried' is my word, not yours, and I understand the docs team has a process. My readers aren't usually reading CU release notes proactively, though. They're reading them after something's already amiss — wrong results with no error, or a dump file they can't explain. By then, the ordering of the Known Issues list matters less than the fact that the workaround costs them parallelism on every query touching SESSION_CONTEXT. If I can help change the four years of 'Date resolved: (blank)', I'm in.
DeleteYes, I'd love to see some collaboration to fix a multi-version bug that impacts us when we are following vendor guidance for context. Sounds like Rebecca is on to something.
DeleteThanks! Three years across three versions is a long time for a known issue tied to vendor-recommended guidance. Hopefully it reaches the fix list soon.
DeleteWow, my team planned to use this to replace `EXECUTE AS USER` for our multi-tenant. A problem like this, without returning any error for the client app, is so dangerous. Thanks for your article, very helpful.
ReplyDeleteGlad it helped! Yeah, the silent failure is the worst part — at least a hard error gives you something to target. Definitely worth testing your use case thoroughly before going to prod. Let me know if I can help!
DeleteSo using SESSION_CONTEXT in v2017, means that sometimes the value checked may not be found, or falsely sometimes the value checked may be found? We are about to introduce the use of SESSION_CONTEXT extensively in our v2017 (on prem, soon to be Azure) database. Maybe holding off until in Azure with DBCC TRACEON(11042, -1); would be best.
ReplyDeleteYou don't have to wait for Azure. DBCC TRACEON(11042, -1) works on 2017 on-prem today. The bug is specific to parallel execution plans, so simple SESSION_CONTEXT reads may never trigger it. The trace flag trade-off is that it forces serial plans server-wide, so test before flipping it in production.
ReplyDelete