From 3e330e39303bfbb317525341078dc629d1ae2f43 Mon Sep 17 00:00:00 2001 From: madelson <1269046+madelson@users.noreply.github.com> Date: Sun, 11 Jan 2026 18:36:32 -0500 Subject: [PATCH] Update RetryableWriteOperationExecutor.cs to avoid losing stack trace when rethrowing originalException MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Today, these methods can give errors like this where the origin stack trace is lost due to improper rethrow: ``` Message:  System.Text.EncoderFallbackException : Unable to translate Unicode character \� at index 55381 to specified code page. Stack Trace:  RetryableWriteOperationExecutor.ExecuteAsync[TResult](OperationContext operationContext, IRetryableWriteOperation`1 operation, RetryableWriteContext context) RetryableWriteOperationExecutor.ExecuteAsync[TResult](OperationContext operationContext, IRetryableWriteOperation`1 operation, IWriteBinding binding, Boolean retryRequested) OperationExecutor.ExecuteWriteOperationAsync[TResult](OperationContext operationContext, IClientSessionHandle session, IWriteOperation`1 operation, Boolean allowChannelPinning) MongoCollectionImpl`1.ExecuteWriteOperationAsync[TResult](IClientSessionHandle session, IWriteOperation`1 operation, Nullable`1 timeout, CancellationToken cancellationToken) MongoCollectionImpl`1.FindOneAndUpdateAsync[TProjection](FilterDefinition`1 filter, UpdateDefinition`1 update, FindOneAndUpdateOptions`2 options, CancellationToken cancellationToken) ``` This makes debugging more challenging. --- .../RetryableWriteOperationExecutor.cs | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/MongoDB.Driver/Core/Operations/RetryableWriteOperationExecutor.cs b/src/MongoDB.Driver/Core/Operations/RetryableWriteOperationExecutor.cs index ff8568bda36..ad7c783f35d 100644 --- a/src/MongoDB.Driver/Core/Operations/RetryableWriteOperationExecutor.cs +++ b/src/MongoDB.Driver/Core/Operations/RetryableWriteOperationExecutor.cs @@ -15,6 +15,7 @@ using System; using System.Collections.Generic; +using System.Runtime.ExceptionServices; using System.Threading.Tasks; using MongoDB.Driver.Core.Bindings; using MongoDB.Driver.Core.Servers; @@ -50,12 +51,11 @@ public static TResult Execute(OperationContext operationContext, IRetry } catch (Exception ex) { + originalException ??= ex; if (!ShouldRetryOperation(operationContext, operation.WriteConcern, context, server, ex, attempt)) { - throw originalException ?? ex; + Rethrow(originalException); } - - originalException ??= ex; } deprioritizedServers ??= new HashSet(); @@ -67,12 +67,12 @@ public static TResult Execute(OperationContext operationContext, IRetry } catch { - throw originalException; + Rethrow(originalException); } if (!AreRetryableWritesSupported(context.ChannelSource.ServerDescription)) { - throw originalException; + Rethrow(originalException); } attempt++; @@ -105,12 +105,11 @@ public static async Task ExecuteAsync(OperationContext operati } catch (Exception ex) { + originalException ??= ex; if (!ShouldRetryOperation(operationContext, operation.WriteConcern, context, server, ex, attempt)) { - throw originalException ?? ex; + Rethrow(originalException); } - - originalException ??= ex; } deprioritizedServers ??= new HashSet(); @@ -122,12 +121,12 @@ public static async Task ExecuteAsync(OperationContext operati } catch { - throw originalException; + Rethrow(originalException); } if (!AreRetryableWritesSupported(context.ChannelSource.ServerDescription)) { - throw originalException; + Rethrow(originalException); } attempt++; @@ -185,5 +184,11 @@ private static bool DoesContextAllowRetries(RetryableWriteContext context, Serve private static bool IsOperationAcknowledged(WriteConcern writeConcern) => writeConcern == null || // null means use server default write concern which implies acknowledged writeConcern.IsAcknowledged; + + private static void Rethrow(Exception exception) + { + // Use ExceptionDispatchInfo to avoid losing the original exception stack trace + ExceptionDispatchInfo.Capture(originalException).Throw(); + } } }