MediatR pipeline behaviors don't forward CancellationToken to next() (v11-style call on MediatR 14) #684

Closed
opened 2026-07-17 21:23:01 +00:00 by spikerj · 1 comment
Owner

Problem

MediatR was upgraded to 14.2.0, whose RequestHandlerDelegate<TResponse> takes a CancellationToken parameter — the documented v12+ contract is next(cancellationToken). But all six pipeline behaviors in SpikerSoft.Business/Behaviors/ still use the pre-v12 parameterless next(), so the request's CancellationToken is not explicitly forwarded down the behavior chain (Roslyn flags this as CA2016 at each site).

Affected (9 call sites): TracingBehavior, PerformanceLoggingBehavior, ValidationBehavior, CachingBehavior (x3), CacheInvalidationBehavior, ActivityTrackingBehavior. Each already receives cancellationToken as a Handle parameter (ValidationBehavior even forwards it to ValidateAsync — just not to next()), so the token is in scope and simply wasn't threaded through.

Fix

next() -> next(cancellationToken) at all 9 sites. This aligns the pipeline with MediatR 14's cancellation-forwarding contract so the request token is explicitly propagated through every behavior to the handler. Strictly safe: forwarding an in-scope token cannot regress behavior.

Scope / honesty note

Framed as a correctness-alignment / modernization: I could not stand up an isolated runtime harness to measure the exact pre-fix propagation (MediatR 13+ gates construction behind a license check that throws in a bare console app), so I am not claiming a specific reproduced cancellation failure — only that the behaviors deviate from MediatR's documented forwarding pattern and this restores it. No behavior change on the success path.

Verification

  • dotnet build SpikerSoft.Business -> Build succeeded, 0 errors.
  • dotnet test SpikerSoft.Business.Tests --filter ~Behavior -> 63 passed, 0 failed (the tests mock next).
  • CI-cost note: only spikersoft-api.yml, spikersoft-notifications.yml, and tests.yml path-filter on SpikerSoft.Business/**, so this rebuilds just those images.
## Problem MediatR was upgraded to **14.2.0**, whose `RequestHandlerDelegate<TResponse>` takes a `CancellationToken` parameter — the documented v12+ contract is `next(cancellationToken)`. But all six pipeline behaviors in `SpikerSoft.Business/Behaviors/` still use the pre-v12 parameterless `next()`, so the request's `CancellationToken` is not explicitly forwarded down the behavior chain (Roslyn flags this as **CA2016** at each site). Affected (9 call sites): `TracingBehavior`, `PerformanceLoggingBehavior`, `ValidationBehavior`, `CachingBehavior` (x3), `CacheInvalidationBehavior`, `ActivityTrackingBehavior`. Each already receives `cancellationToken` as a `Handle` parameter (ValidationBehavior even forwards it to `ValidateAsync` — just not to `next()`), so the token is in scope and simply wasn't threaded through. ## Fix `next()` -> `next(cancellationToken)` at all 9 sites. This aligns the pipeline with MediatR 14's cancellation-forwarding contract so the request token is explicitly propagated through every behavior to the handler. Strictly safe: forwarding an in-scope token cannot regress behavior. ## Scope / honesty note Framed as a correctness-alignment / modernization: I could not stand up an isolated runtime harness to measure the exact pre-fix propagation (MediatR 13+ gates construction behind a license check that throws in a bare console app), so I am **not** claiming a specific reproduced cancellation failure — only that the behaviors deviate from MediatR's documented forwarding pattern and this restores it. No behavior change on the success path. ## Verification - `dotnet build SpikerSoft.Business` -> Build succeeded, 0 errors. - `dotnet test SpikerSoft.Business.Tests --filter ~Behavior` -> **63 passed, 0 failed** (the tests mock `next`). - CI-cost note: only `spikersoft-api.yml`, `spikersoft-notifications.yml`, and `tests.yml` path-filter on `SpikerSoft.Business/**`, so this rebuilds just those images.
Author
Owner

Resolved in spikersoft-backend PR #382 (merged to master). Forwarded the request CancellationToken through all six MediatR pipeline behaviors (next(cancellationToken)), aligning them with the MediatR 14 contract. CI: both amd64+arm64 builds and unit tests passed green. Closing.

Resolved in spikersoft-backend PR #382 (merged to `master`). Forwarded the request CancellationToken through all six MediatR pipeline behaviors (next(cancellationToken)), aligning them with the MediatR 14 contract. CI: both amd64+arm64 builds and unit tests passed green. Closing.
Sign in to join this conversation.