diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 6f7624e..d4df942 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## 5.7.3
+- Fixed
+ - Corrected the shutdown `OperationCanceledException` guard introduced in 5.7.2. The previous guard checked `oce.CancellationToken.IsCancellationRequested`, which was always `false` because the Azure ServiceBus SDK raises `ProcessErrorAsync` with `CancellationToken.None` during processor shutdown. The guard now matches any `OperationCanceledException`, which is safe since genuine transport errors surface as `ServiceBusException`.
+
## 5.7.2
- Fixed
- Suppressed spurious `OperationCanceledException` / `TaskCanceledException` APM error entries during pod graceful shutdown. When the Service Bus receive loop is cancelled with a requested cancellation token, the exception is now logged at `Warning` level instead of `Error`.
diff --git a/src/Ev.ServiceBus/Management/Wrappers/ReceiverWrapper.cs b/src/Ev.ServiceBus/Management/Wrappers/ReceiverWrapper.cs
index 58e6fc3..abc180c 100644
--- a/src/Ev.ServiceBus/Management/Wrappers/ReceiverWrapper.cs
+++ b/src/Ev.ServiceBus/Management/Wrappers/ReceiverWrapper.cs
@@ -132,7 +132,7 @@ private void TrySetReceptionRegistrationOnContext(MessageContext context, IServi
///
protected async Task OnExceptionOccured(ProcessErrorEventArgs exceptionEvent)
{
- if (exceptionEvent.Exception is OperationCanceledException oce && oce.CancellationToken.IsCancellationRequested)
+ if (exceptionEvent.Exception is OperationCanceledException)
{
_messageProcessingLogger.LogWarning(
"[Ev.ServiceBus] Receive loop cancelled for {ClientType} '{ResourceId}' during shutdown.",
diff --git a/tests/Ev.ServiceBus.UnitTests/ReceiverWrapperTests.cs b/tests/Ev.ServiceBus.UnitTests/ReceiverWrapperTests.cs
index d6086b2..b735f34 100644
--- a/tests/Ev.ServiceBus.UnitTests/ReceiverWrapperTests.cs
+++ b/tests/Ev.ServiceBus.UnitTests/ReceiverWrapperTests.cs
@@ -31,20 +31,44 @@ private static TestableReceiverWrapper CreateWrapper(ILogger>();
var wrapper = CreateWrapper(mockLogger.Object);
- using var cts = new CancellationTokenSource();
- cts.Cancel();
+ // Azure SDK raises ProcessErrorAsync with CancellationToken.None during shutdown —
+ // the token on the exception is not the shutdown token, so IsCancellationRequested is false.
+ var args = new ProcessErrorEventArgs(
+ new OperationCanceledException("shutdown", CancellationToken.None),
+ ServiceBusErrorSource.Receive,
+ "test-namespace",
+ "test-queue",
+ CancellationToken.None);
+
+ await wrapper.InvokeOnExceptionOccuredAsync(args);
+
+ mockLogger.Verify(
+ x => x.Log(
+ LogLevel.Error,
+ It.IsAny(),
+ It.Is((v, t) => true),
+ It.IsAny(),
+ It.Is>((v, t) => true)),
+ Times.Never());
+ }
+
+ [Fact]
+ public async Task OnExceptionOccured_WithTaskCanceledException_DoesNotLogError()
+ {
+ var mockLogger = new Mock>();
+ var wrapper = CreateWrapper(mockLogger.Object);
var args = new ProcessErrorEventArgs(
- new OperationCanceledException("shutdown", cts.Token),
+ new TaskCanceledException(),
ServiceBusErrorSource.Receive,
"test-namespace",
"test-queue",
- cts.Token);
+ CancellationToken.None);
await wrapper.InvokeOnExceptionOccuredAsync(args);