Skip to content

Preserve the original exception when SqlDataReader teardown also times out #4638

Description

@mdaigle

Describe the bug

When a per-row transform throws while processing a result set, reader teardown can subsequently time out while draining the remaining rows. The teardown exception, ending in Win32Exception (258): Unknown error 258, replaces the original transform exception entirely. The caller cannot determine why row processing failed.

This variant was confirmed in the Cause B analysis on #1530. The follow-up comment proposes surfacing both exceptions through an AggregateException.

Exception message: Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
Inner exception: System.ComponentModel.Win32Exception (258): Unknown error 258
Stack trace: The teardown timeout replaces the exception thrown by the per-row transform.

To reproduce

  1. Execute a query that returns enough rows that draining them exceeds a short CommandTimeout.
  2. Throw an exception from a per-row transform before the result set is consumed.
  3. Close the reader during exception cleanup.
  4. Observe that the close-time timeout replaces the transform exception.

The linked analysis reports a deterministic reproduction.

Expected behavior

Preserve and surface both the original row-processing exception and the reader teardown exception, for example through an AggregateException.

Further technical details

Microsoft.Data.SqlClient version: Reproduced with the stacks covered by the linked Cause B analysis
.NET target: Sync and async reader teardown paths are relevant
SQL Server version: Reproduced with SQL Server in Docker
Operating system: Linux

Additional context

This issue tracks exception preservation separately from improving the opaque Cause B timeout message. Parent issue: #1530.

Activity

  1. added theissue type on Sep 3, 2026
  2. priyankatiwari08 commented on Sep 17, 2026

    @priyankatiwari08
    Contributor

    /triage

  3. github-actions commented on Sep 17, 2026

    @github-actions

    🔍 Triage Summary (on-demand re-triage)

    Check Result
    Issue type Bug
    Environment ⚠️ Missing: specific Microsoft.Data.SqlClient version, exact .NET target framework (TFM), and specific SQL Server version/edition (only "SQL Server in Docker" and OS "Linux" given)
    Area Area\Managed SNI
    Duplicates None found (issue is itself a tracked sub-issue; parent #1530 covers the broader "Unknown error 258" investigation and cause analysis)
    Regression Not indicated

    Analysis

    This is a well-scoped sub-issue of #1530, tracking a specific exception-preservation gap: when a per-row transform throws during result-set processing and SqlDataReader teardown subsequently times out while draining remaining rows, the teardown timeout (surfacing as Win32Exception (258)) currently replaces the original transform exception, hiding the true root cause from the caller. The reporter proposes wrapping both exceptions in an AggregateException during reader close/dispose, affecting both sync and async teardown paths. This is a diagnosability/exception-handling issue in the reader close path (likely TdsParserStateObject/SqlDataReader.Close internals), not a new protocol feature. Severity: P2 (does not cause data loss, but significantly hampers root-cause diagnosis of an already-confusing timeout scenario).

    Next Steps

    • Since this issue documents a deterministic, previously-analyzed repro (per the linked Cause B analysis in Intermittent Unknown error 258 with no obvious cause #1530), consider assigning it to Copilot coding agent to investigate SqlDataReader/TdsParser teardown/close logic for both sync and async paths, and implement wrapping of the original per-row transform exception together with the teardown timeout exception (e.g., via AggregateException) so callers can observe both. Ensure test coverage for both sync and async reader-close code paths per repo testing conventions.
    • If precise environment details (exact SqlClient version, TFM, SQL Server version) are available, they would help pin down whether this reproduces uniformly across supported versions, but given the issue is a design/exception-handling fix tied to a confirmed analysis in the parent issue, they are not strictly blocking for investigation.
    • Recommend reviewing the parent issue Intermittent Unknown error 258 with no obvious cause #1530 and its linked Cause B analysis comment before starting implementation, to ensure the fix aligns with the broader "Unknown error 258" root-cause work.

    Note: This triage summary is auto-generated by an AI agent. The analysis and suggestions above have not been verified by a human maintainer. Please treat as preliminary guidance only.

    Generated by SqlClient Issue Auto-Triage for #4638 · copilot · auto · 56.5 AIC · ⌖ 13.1 AIC · ⊞ 11.9K · ◷

  4. tmorejon commented on Sep 20, 2026

    @tmorejon

    Hi,

    I'd like to investigate this issue.

    I'll start by reproducing the deterministic teardown-timeout scenario and reviewing the previous SqlDataReader disposal work around #672/#920.

    In particular, I want to determine where SqlClient still has access to both the original processing failure and the teardown failure, so the fix can preserve both without changing unrelated disposal semantics.

    I'll cover both synchronous and asynchronous reader teardown paths where applicable.

    If this direction sounds reasonable, I'm happy to work on it.

  5. mdaigle commented on Sep 21, 2026

    @mdaigle
    ContributorAuthor

    Hi @tmorejon, that sounds great. Investigation here would be very much welcomed.

    Before you write any code, make sure to share a brief design for the changes you would make to solve the issue. The team will review your design and approve or suggest changes. We will let you know when the design looks good and is ready to proceed to PR. This helps reduce churn in the PR review process. Thank you!

  6. moved this from To triage to Backlog in SqlClient Boardon Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area\Managed SNIIssues that are targeted to the Managed SNI codebase.

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions