SnowDriven Research · Reference

.NET 8 to .NET 10: the breaking changes that hit web apps

Microsoft’s six breaking-change lists between .NET 8 and .NET 10 have 194 entries. We read every one for an ASP.NET Core web app, an API or a worker service: 6 are likely to need attention, 33 are possible and 31 are rare. Each links to Microsoft’s own page, checked on 25 October 2026.

For
.NET teams and their leads
Lists read
Six, from Microsoft
Entries listed
194
On this page
70
Checked
25 Oct 2026

The short answer

The 6 changes we rate likely for a typical web app or worker. Each has its entry below.

Last updated

  1. URI query and fragment redaction in IHttpClientFactory logs

    .NET 9. IHttpClientFactory’s default logging now replaces the URI query with * and removes user info and fragments in messages passed to ILogger.

  2. Default .NET images use Ubuntu

    .NET 10. Tags without an explicit OS (for example sdk:10.0) now point to Ubuntu 24.04 “Noble” instead of Debian, and Debian-based .NET 10 images aren’t shipped.

  3. 'dotnet restore' audits transitive packages

    .NET 10. For projects targeting .NET 10 or later, NuGetAuditMode defaults to “all”, so known-vulnerable transitive packages raise warnings, which can fail restore when warnings are errors.

  4. Deprecation of WithOpenApi extension method

    ASP.NET Core 10. WithOpenApi is deprecated; calling it produces warning ASPDEPR002, though the call still compiles and runs.

  5. Exception is thrown when applying migrations if there are pending model changes

    EF Core 9. If the model differs from the last migration’s snapshot, dotnet ef database update, Migrate and MigrateAsync now throw instead of silently skipping the changes.

  6. Exception is thrown when applying migrations in an explicit transaction

    EF Core 9. Migrate and MigrateAsync now manage their own transaction and execution strategy, so calling them inside a user-started transaction throws.

Before you change anything. This page is general information, not advice for your system. Each entry summarizes Microsoft’s own page, checked on 25 October 2026. Microsoft can change its lists, and it says the .NET 10 list is a work in progress and not complete, so read the linked page before you act on an entry. Whether a change is likely, possible or rare for you is our judgement for a typical app, not Microsoft’s. Back up, test every change on a copy that isn’t in production, keep a way back, and follow your own change process. You follow these steps at your own risk (terms). SnowDriven isn’t affiliated with Microsoft (trademarks).

How to use this list

The upgrade steps (SDK, retarget, packages, images, test) are in our .NET 8 end-of-support guide. This page is the part of that work Microsoft’s lists leave unsorted.

  1. Start with the likely ones

    They’re the ones a typical app is most likely to meet: two are about container images and restore, two about EF Core migrations, one about logging and one about a template call.

  2. Search for the possible ones

    Each entry’s “How to tell” names what to search your solution for: an API, a setting, a package or a warning code. No match, no work.

  3. Build with warnings visible

    Many entries are new compiler or restore warnings (codes starting ASPDEPR, SYSLIB or NU). With TreatWarningsAsErrors on, each one fails the build, so decide case by case whether to fix it or exempt it in writing.

  4. Then test the behavior

    Behavioral changes compile cleanly and show up at runtime, in logs, or in what a client receives. Run the workflows the business depends on, on a staging copy, before the first production deployment.

Already on the latest .NET 8 patch?

Microsoft shipped 4 of these changes in .NET 8 servicing releases too, so an app on that patch or later already behaves this way:

Support for .NET 8 and .NET 9 ends on 10 November 2026. What that means, how to check what you run and the upgrade path: .NET 8 and 9 end of support.

Likely (6)

Changes most web apps or workers moving from .NET 8 will meet. Check each one.

Possible (33)

Changes that hit some web apps, depending on what the code uses. Search your solution for what’s under “How to tell”.

.NET runtime, libraries and SDK · 17

  • .NET 9DeploymentBehavioral changeEnvironment variables take precedence in app runtime configuration settingsWhen an environment variable and runtimeconfig.json (or project file) set the same runtime setting, the environment variable now wins. Previously runtimeconfig.json took precedence.
    How to tell
    DOTNET_* runtime-config environment variables (Microsoft’s example: DOTNET_gcServer) set in the container, App Service settings or host that conflict with runtimeconfig.json/csproj values such as System.GC.Server.
    What to do
    Unset the environment variable or set it to the value you actually want.
    Why it’s possible (our view)
    Hosting platforms and Dockerfiles often set DOTNET_* variables that were silently ignored before and now take effect.

    Microsoft’s page for this change

  • .NET 9SerializationBehavioral changeIn-box BinaryFormatter implementation removed and always throwsThe in-box BinaryFormatter now throws on use, even with the settings that previously enabled it; those settings are removed.
    How to tell
    Any use of System.Runtime.Serialization.Formatters.Binary.BinaryFormatter, directly or through a dependency (for example legacy caching or session code); exceptions at runtime.
    What to do
    Move to a different serialization format (see the BinaryFormatter migration guide). An unsupported separate NuGet package exists if you accept the risk.
    Why it’s possible (our view)
    Rare in new code, but legacy caches, session state and older libraries still use it, and it fails at runtime, not compile time.

    Microsoft’s page for this change

  • .NET 9NetworkingBehavioral changeHttpClientFactory uses SocketsHttpHandler as primary handlerThe default primary handler for IHttpClientFactory clients is now SocketsHttpHandler, with PooledConnectionLifetime matching HandlerLifetime. Casting it to HttpClientHandler throws InvalidCastException.
    How to tell
    Code that casts the default primary handler, for example ConfigurePrimaryHttpMessageHandler((h, _) => ((HttpClientHandler)h)…); an InvalidCastException saying SocketsHttpHandler can’t be cast to HttpClientHandler.
    What to do
    Explicitly configure a primary handler per client or via ConfigureHttpClientDefaults, or check for both HttpClientHandler and SocketsHttpHandler.
    Why it’s possible (our view)
    Only code that casts the default primary handler (for example, to set client certificates, cookies or a proxy) breaks.

    Microsoft’s page for this change

  • .NET 9NetworkingBehavioral changeHttpClient metrics report server.port unconditionallyhttp.client.request.duration, http.client.connection.duration and http.client.open_connections now always report server.port, including default ports 80/443, which can break existing monitoring queries.
    How to tell
    Prometheus or other monitoring queries over HttpClient metrics that assume server.port is absent for ports 80/443.
    What to do
    No action unless you use these HttpClient metrics; if you do, update monitoring queries such as Prometheus queries.
    Why it’s possible (our view)
    Only affects teams that export HttpClient metrics (for example via OpenTelemetry) and query on server.port.

    Microsoft’s page for this change

  • .NET 9Core .NET librariesSource incompatibleAPI obsoletions with non-default diagnostic IDs (.NET 9)New obsoletion warnings SYSLIB0009, SYSLIB0014 (ServicePointManager fully obsolete), SYSLIB0054 to SYSLIB0056 and SYSLIB0057 (X509Certificate2 binary/file constructors) can’t be suppressed via CS0618.
    How to tell
    Build warnings SYSLIB0009, SYSLIB0014, SYSLIB0054, SYSLIB0055, SYSLIB0056, SYSLIB0057; build failures if TreatWarningsAsErrors is on.
    What to do
    Follow each diagnostic’s linked guidance; suppress, if needed, using the specific SYSLIB ID rather than CS0618.
    Why it’s possible (our view)
    ServicePointManager and X509Certificate2 file constructors are still common in older server code; impact is build warnings unless warnings are errors.

    Microsoft’s page for this change

  • .NET 9CryptographySource incompatibleSome X509Certificate2 and X509Certificate constructors are obsoleteX509Certificate/X509Certificate2 constructors taking byte[], ReadOnlySpan<byte> or a file path, and X509Certificate2Collection.Import, are obsolete and produce warning SYSLIB0057.
    How to tell
    Warning SYSLIB0057 on new X509Certificate2(path/bytes, ...) or X509Certificate2Collection.Import calls.
    What to do
    Follow the guidance on Microsoft’s SYSLIB0057 page, which the change links to.
    Why it’s possible (our view)
    Loading certificates from files or bytes (TLS client certificates, signing keys) is common in server apps; it’s a compile-time warning.

    Microsoft’s page for this change

  • .NET 9Core .NET librariesSource incompatibleAmbiguous overload resolution affecting StringValues implicit operatorsNew params ReadOnlySpan overloads of String.Concat, String.Join, Path.Combine, Path.Join and StringBuilder.AppendJoin make calls that pass StringValues ambiguous, so the compiler reports CS0121.
    How to tell
    Compiler error CS0121 (“The call is ambiguous …”) on String.Join, String.Concat, Path.Combine, Path.Join or StringBuilder.AppendJoin calls involving StringValues.
    What to do
    Cast arguments to the intended type or use named parameters so the intended overload is selected.
    Why it’s possible (our view)
    StringValues is common in header and query handling code in web apps; the break shows up at compile time.

    Microsoft’s page for this change

  • .NET 10ExtensionsBehavioral changeBackgroundService runs all of ExecuteAsync as a TaskBackgroundService now runs all of ExecuteAsync on a background thread; the synchronous part before the first await no longer runs during startup or blocks other services.
    How to tell
    BackgroundService.ExecuteAsync implementations whose code before the first await must finish before other hosted services or the app start.
    What to do
    Move startup-critical work to the constructor or an overridden StartAsync (before base.StartAsync), or implement IHostedLifecycleService.
    Why it’s possible (our view)
    Many workers subclass BackgroundService; only those relying on the synchronous prefix’s startup ordering break.

    Microsoft’s page for this change

  • .NET 10ExtensionsBehavioral changeNull values preserved in configurationThe configuration binder now binds explicit null values (including array elements and empty arrays) instead of skipping them; nulls on non-nullable value types become default(T).
    How to tell
    appsettings.json (or other provider) entries set to null; options properties that used to keep their defaults now become null or default.
    What to do
    With JSON, replace null with "" to restore the old result; for other providers, remove null entries from configuration.
    Why it’s possible (our view)
    Explicit nulls in appsettings files are fairly common and silently change bound options values.

    Microsoft’s page for this change

  • .NET 10ExtensionsBehavioral changeMessage no longer duplicated in Console log outputWith the JSON console formatter, Message now typically appears only at the top level, not repeated inside the State object.
    How to tell
    Log pipelines that parse JSON console logs (AddJsonConsole) and read Message from the State object.
    What to do
    Read the top-level Message field instead of the one inside State.
    Why it’s possible (our view)
    Containerized apps often ship JSON console logs to collectors; only parsers that read State.Message break.

    Microsoft’s page for this change

  • .NET 10Core .NET librariesBehavioral changeDefault trace context propagator updated to W3C standardDistributedContextPropagator’s default is now the W3C propagator: it uses the baggage header instead of Correlation-Context, enforces W3C encoding, and supports only W3C-format parent IDs.
    How to tell
    Services exchanging Correlation-Context headers or non-W3C (hierarchical) trace parent IDs with other systems; DistributedContextPropagator.Current.
    What to do
    To keep the legacy behavior, set DistributedContextPropagator.Current = DistributedContextPropagator.CreatePreW3CPropagator().
    Why it’s possible (our view)
    Matters for distributed systems that interoperate with older services using legacy correlation headers.

    Microsoft’s page for this change

  • .NET 10Core .NET librariesSource incompatibleSystem.Linq.AsyncEnumerable in .NET 10.NET 10 includes AsyncEnumerable with LINQ for IAsyncEnumerable<T>, replacing the community System.Linq.Async package and potentially causing ambiguity compile errors.
    How to tell
    Direct or transitive references to the System.Linq.Async package; ambiguous-call compile errors on IAsyncEnumerable LINQ methods.
    What to do
    Remove System.Linq.Async or upgrade it to 7.0.0; for transitive references use ExcludeAssets=compile (or all).
    Why it’s possible (our view)
    System.Linq.Async is a widely used dependency, often pulled in transitively.

    Microsoft’s page for this change

  • .NET 10Core .NET librariesBehavioral changeC# 14 overload resolution with span parametersC# 14 span conversions make span-based methods (for example MemoryExtensions) bind in more places, including Expression lambdas, which then fail at runtime when compiled with interpretation.
    How to tell
    Expression trees containing calls like array.Contains(x) that now bind to MemoryExtensions.Contains; runtime exceptions from Expression.Compile with interpretation.
    What to do
    Force non-span overloads: cast to the exact parameter type (for example IEnumerable<T>), use AsEnumerable(), or call Enumerable methods statically.
    Why it’s possible (our view)
    Expression-tree code (dynamic filters, rules engines) is common; impact depends on interpretation being used.

    Microsoft’s page for this change

  • .NET 10Core .NET librariesSource incompatibleAPI obsoletions with non-default diagnostic IDs (.NET 10)New obsoletion warnings: SYSLIB0058 (SslStream cipher/hash properties), SYSLIB0059, SYSLIB0060 (Rfc2898DeriveBytes constructors), SYSLIB0061 (Queryable.MaxBy and MinBy with IComparer<TSource>), SYSLIB0062 (XsltSettings.EnableScript).
    How to tell
    Build warnings SYSLIB0058-SYSLIB0062, for example on new Rfc2898DeriveBytes(...); build failures if TreatWarningsAsErrors.
    What to do
    Follow each diagnostic’s guidance (for example, use Rfc2898DeriveBytes.Pbkdf2, SslStream.NegotiatedCipherSuite); suppress only by the specific SYSLIB ID.
    Why it’s possible (our view)
    Rfc2898DeriveBytes constructors are common in password-hashing code; it’s a compile-time warning.

    Microsoft’s page for this change

  • .NET 10NetworkingBehavioral changeMailAddress enforces validation for consecutive dotsMailAddress now throws FormatException for addresses with consecutive dots in the local or domain part (for example test..address@example.com), per RFC 5322/2822.
    How to tell
    new MailAddress(...) calls; FormatException for previously accepted addresses in sign-up, import or email-sending code.
    What to do
    Make sure such addresses aren’t passed, or handle the FormatException (for example with try/catch or prior validation).
    Why it’s possible (our view)
    Web apps commonly parse user-supplied email addresses with MailAddress; stored legacy data may contain such addresses.

    Microsoft’s page for this change

  • .NET 10SerializationBehavioral changeSystem.Text.Json checks for property name conflictsSystem.Text.Json now throws InvalidOperationException early when user properties conflict with metadata names ($type, $id, $ref or custom discriminator names) under polymorphism or reference preservation.
    How to tell
    InvalidOperationException: The type ... contains property ... that conflicts with an existing metadata property name when serializing polymorphic or reference-preserving types.
    What to do
    Rename conflicting properties, or apply [JsonIgnore] if the property must stay.
    Why it’s possible (our view)
    Polymorphic DTOs with their own “Type”-style discriminator property are a common pattern in APIs.

    Microsoft’s page for this change

  • .NET 10SDK and MSBuildSource incompatibleNU1510 is raised for direct references pruned by NuGetWith pruning enabled, projects targeting .NET 10+ get warning NU1510 for direct package references that the framework already provides (unnecessary references).
    How to tell
    Warning NU1510 on PackageReference items such as System.Text.Json; build failures if warnings are errors.
    What to do
    Remove the unnecessary reference, or for multi-targeting include it conditionally only for frameworks that need it.
    Why it’s possible (our view)
    Upgraded apps often carry explicit references to framework-provided packages left over from older targets.

    Microsoft’s page for this change

ASP.NET Core · 9

  • ASP.NET Core 9Behavioral changeIn .NET 8.0.17Forwarded headers middleware ignores X-Forwarded-* headers from unknown proxiesForwarded headers middleware now processes X-Forwarded-* headers only from proxies listed in KnownProxies/KnownNetworks; headers from unknown sources are ignored.
    How to tell
    UseForwardedHeaders behind a TLS-terminating proxy or load balancer; symptoms Microsoft names: infinite HTTPS redirects, or authentication failing when an HTTPS request is expected.
    What to do
    Add every legitimate proxy to KnownProxies or KnownNetworks; clearing both lists or ASPNETCORE_FORWARDEDHEADERS_ENABLED=true restores old behavior (not recommended).
    Why it’s possible (our view)
    Common for apps behind a proxy or load balancer, but it shipped in .NET 8.0.17, so an up-to-date .NET 8 app already has it.

    Microsoft’s page for this change

  • ASP.NET Core 9Behavioral changeHostBuilder enables ValidateOnBuild/ValidateScopes in development environmentIn the Development environment, HostBuilder now turns on ValidateOnBuild and ValidateScopes unless UseDefaultServiceProvider sets them, so DI registration problems surface at startup.
    How to tell
    DI validation errors at startup when running in Development (affected APIs: HostBuilder, HostBuilder.Build()).
    What to do
    Fix the reported DI registration problem; if you can’t, disable validation with UseDefaultServiceProvider.
    Why it’s possible (our view)
    Only hits apps with latent DI lifetime/registration errors, and only in Development.

    Microsoft’s page for this change

  • ASP.NET Core 9Behavioral changeMiddleware types with multiple constructorsIf the DI container doesn’t implement IServiceProviderIsService, middleware with several satisfiable constructors now throws instead of picking the one with most parameters.
    How to tell
    InvalidOperationException Multiple constructors accepting all given argument types have been found...; Microsoft names CookiePolicyMiddleware with Autofac.Extensions.DependencyInjection 7.x.
    What to do
    Upgrade to a DI container implementing IServiceProviderIsService, or put ActivatorUtilitiesConstructorAttribute on the preferred middleware constructor.
    Why it’s possible (our view)
    Only apps using a third-party DI container (Microsoft names Autofac 7.x); the default container is unaffected.

    Microsoft’s page for this change

  • ASP.NET Core 10Behavioral changeException diagnostics suppressed when TryHandleAsync returns trueWhen an IExceptionHandler.TryHandleAsync returns true, the exception handler middleware no longer logs the exception, emits the HandledException event, or adds error.type to the duration metric.
    How to tell
    Apps with IExceptionHandler implementations noticing handled exceptions vanish from logs/telemetry (UnhandledException log, http.server.request.duration error.type tag).
    What to do
    If you still want telemetry for handled exceptions, set ExceptionHandlerOptions.SuppressDiagnosticsCallback to return false.
    Why it’s possible (our view)
    Only apps using IExceptionHandler (added in .NET 8) and relying on middleware-emitted logs/metrics.

    Microsoft’s page for this change

  • ASP.NET Core 10Source incompatible and Behavioral changeIActionContextAccessor and ActionContextAccessor are obsoleteIActionContextAccessor and ActionContextAccessor are marked obsolete (ASPDEPR006); endpoint metadata is available via HttpContext.GetEndpoint().
    How to tell
    Warning ASPDEPR006 wherever IActionContextAccessor/ActionContextAccessor is injected or registered (often alongside IUrlHelperFactory in MVC apps).
    What to do
    Inject IHttpContextAccessor and read metadata via HttpContext.GetEndpoint(), for example GetMetadata<ActionDescriptor>().
    Why it’s possible (our view)
    Seen in older MVC codebases; warning only. The overview labels it Source incompatible/behavioral change but the change page itself says only source compatibility.

    Microsoft’s page for this change

  • ASP.NET Core 10Source incompatibleIPNetwork and ForwardedHeadersOptions.KnownNetworks are obsoleteMicrosoft.AspNetCore.HttpOverrides.IPNetwork and ForwardedHeadersOptions.KnownNetworks are obsolete (ASPDEPR005) in favor of System.Net.IPNetwork and KnownIPNetworks.
    How to tell
    Warning ASPDEPR005 on KnownNetworks or Microsoft.AspNetCore.HttpOverrides.IPNetwork in forwarded headers configuration.
    What to do
    Switch to System.Net.IPNetwork and the KnownIPNetworks property.
    Why it’s possible (our view)
    Apps behind proxies that configure KnownNetworks; warning only.

    Microsoft’s page for this change

  • ASP.NET Core 10Source incompatibleRazor runtime compilation is obsoleteRazor runtime compilation APIs are obsolete (ASPDEPR003); Microsoft recommends build-time compilation for production and Hot Reload for development.
    How to tell
    Warning ASPDEPR003 on AddRazorRuntimeCompilation (and the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation types).
    What to do
    Remove AddRazorRuntimeCompilation calls and use Hot Reload instead.
    Why it’s possible (our view)
    Common in MVC/Razor Pages apps for dev-time view editing; warning only.

    Microsoft’s page for this change

  • ASP.NET Core 10Source incompatibleWebHostBuilder, IWebHost, and WebHost are obsoleteWebHostBuilder (ASPDEPR004) and IWebHost/WebHost (ASPDEPR008) are obsolete; HostBuilder and WebApplicationBuilder are where future investment goes.
    How to tell
    Warnings ASPDEPR004/ASPDEPR008 on new WebHostBuilder(), WebHost.CreateDefaultBuilder, IWebHost, including test code building a TestServer from a WebHostBuilder.
    What to do
    Migrate to HostBuilder with ConfigureWebHost (use host.GetTestServer() for tests) or to WebApplicationBuilder.
    Why it’s possible (our view)
    Apps carried forward from ASP.NET Core 2.x and TestServer-based tests; apps on WebApplication or Host builders are unaffected. Warning only.

    Microsoft’s page for this change

EF Core · 7

  • EF Core 10Medium impactEF tools now require framework to be specified for multi-targeted projectsdotnet-ef commands on projects using <TargetFrameworks> (multiple TFMs) now fail unless --framework is specified.
    How to tell
    Error The project targets multiple frameworks. Use the --framework option to specify which target framework to use.
    What to do
    Pass --framework (for example --framework net10.0) to every EF tools command on multi-targeted projects.
    Why it’s possible (our view)
    Microsoft rates it Medium, but only multi-targeted projects; most web apps target a single framework.

    Microsoft’s page for this change

  • EF Core 10Low impactParameterized collections now use multiple parameters by defaultLINQ Contains over in-memory collections now translates to multiple scalar parameters (IN (@ids1, @ids2, …)) instead of one JSON array parameter; performance can differ.
    How to tell
    Queries like ids.Contains(b.Id) generating different SQL; performance regressions, especially with large collections.
    What to do
    If regressions appear, set UseParameterizedCollectionMode globally, or use EF.Parameter / EF.Constant per query.
    Why it’s possible (our view)
    Microsoft rates it Low and usually harmless, but Contains-over-list queries are very common, so worth load-testing.

    Microsoft’s page for this change

  • EF Core 10Low impactSQL parameter names are now simplifiedGenerated SQL parameter names drop the __ prefix and counter (@__city_0 becomes @city); queries are functionally identical.
    How to tell
    Snapshot tests comparing SQL text, interceptors/loggers parsing CommandText or ParameterName; a query-plan recompilation spike after deployment.
    What to do
    Update code or tests depending on exact parameter names; large systems should plan for temporary plan recompilation after deploy.
    Why it’s possible (our view)
    Microsoft rates it Low; touches SQL-text tests and causes a one-off plan-cache churn on busy databases.

    Microsoft’s page for this change

  • EF Core 10Low impactSQL Server json data type used by default on Azure SQL and compatibility level 170With UseAzureSql or compatibility level 170+, JSON-mapped primitive collections and owned types use the json type instead of nvarchar(max); existing apps get an altering migration.
    How to tell
    A new migration altering nvarchar(max) JSON columns to json after upgrading; failing queries such as DISTINCT over JSON arrays.
    What to do
    Set a compatibility level below 170 (for example UseCompatibilityLevel(160)), or set HasColumnType("nvarchar(max)") on specific properties.
    Why it’s possible (our view)
    Microsoft rates it Low; only Azure SQL (UseAzureSql) or compat level 170 apps using JSON-mapped columns or primitive collections.

    Microsoft’s page for this change

  • EF Core 10Low impactSQL Server: Microsoft.Data.SqlClient adds a broker dependencyMicrosoft.Data.SqlClient 6.1.6, used by the SQL Server provider, depends on Microsoft.Identity.Client.Broker, which can drastically increase published app size.
    How to tell
    Noticeably larger publish output or container images for apps using the EF Core SQL Server provider.
    What to do
    If not using Entra ID authentication, reference Microsoft.Data.SqlClient 7.1.x explicitly to override EF Core’s version.
    Why it’s possible (our view)
    Microsoft rates it Low; can enlarge publish output for any SQL Server app, which matters mostly for container image size.

    Microsoft’s page for this change

  • EF Core 10High impactUsing GetDateTimeOffset without an offset now assumes UTCMicrosoft.Data.Sqlite 10 treats textual timestamps without an offset as UTC (previously local time) when read with GetDateTimeOffset.
    How to tell
    SQLite apps reading offset-less text timestamps as DateTimeOffset, with values shifted by the server’s local UTC offset.
    What to do
    Adjust code; as a temporary last resort set the Microsoft.Data.Sqlite.Pre10TimeZoneHandling AppContext switch to true.
    Why it’s possible (our view)
    Microsoft rates it High (likely for SQLite apps storing such timestamps), but only apps on SQLite.

    Microsoft’s page for this change

  • EF Core 10High impactUsing GetDateTime with an offset now returns value in UTCMicrosoft.Data.Sqlite 10 converts textual timestamps that include an offset to UTC and returns DateTimeKind.Utc from GetDateTime (previously DateTimeKind.Local).
    How to tell
    SQLite apps reading offset-bearing text timestamps as DateTime; values and DateTime.Kind change from Local to Utc.
    What to do
    Adjust code; as a temporary last resort set the Microsoft.Data.Sqlite.Pre10TimeZoneHandling AppContext switch to true.
    Why it’s possible (our view)
    Microsoft rates it High (likely for affected SQLite apps), but only apps on SQLite with offset-bearing text timestamps.

    Microsoft’s page for this change

Rare (31)

Changes that need a specific feature, platform or pattern. Read the ones for features you use.

.NET runtime, libraries and SDK · 15

  • .NET 9ContainersBehavioral change.NET 9 container images no longer install zlib.NET 9 container images stop installing zlib, and no longer update it where the base image already has it, because the runtime now statically links zlib-ng.
    How to tell
    Your app or a native dependency loads the system zlib package inside an official .NET container image.
    What to do
    Usually nothing. If the app directly depends on zlib, install it yourself in the Dockerfile with the package manager.
    Why it’s rare (our view)
    The runtime no longer needs zlib; only apps or native libraries that use the system zlib directly are affected.

    Microsoft’s page for this change

  • .NET 9SerializationBehavioral changeNullable JsonDocument properties deserialize to JsonValueKind.NullDeserializing a JSON null into JsonDocument now returns a non-null JsonDocument whose RootElement.ValueKind is JsonValueKind.Null, instead of null.
    How to tell
    Code that deserializes into JsonDocument (or JsonDocument? properties) and checks the result for null.
    What to do
    Update consuming code to expect JsonValueKind.Null rather than a null reference.
    Why it’s rare (our view)
    Only matters for models that use JsonDocument properties and null-check them.

    Microsoft’s page for this change

  • .NET 9NetworkingBehavioral changeHttpClientFactory logging redacts header values by defaultIf RedactLoggedHeaders isn’t called, IHttpClientFactory’s Trace-level request/response header logs now replace all header values with * instead of logging them as-is.
    How to tell
    Trace-level System.Net.Http.HttpClient.* logs show Header: *; diagnostics that relied on logged header values.
    What to do
    Call RedactLoggedHeaders (per client or via ConfigureHttpClientDefaults) to choose which headers are redacted, preferably with an allow-list.
    Why it’s rare (our view)
    Header logging is Trace level, which few production apps enable; the effect is on diagnostics, not behavior.

    Microsoft’s page for this change

  • .NET 9Core .NET librariesBehavioral changeIn .NET 8.0.9FromKeyedServicesAttribute no longer injects non-keyed parameterWhen [FromKeyedServices] names a keyed service that isn’t registered, an InvalidOperationException is thrown instead of possibly injecting a wrong, non-keyed service. Also backported to .NET 8.0.9.
    How to tell
    [FromKeyedServices(key)] parameters; InvalidOperationException at resolution time.
    What to do
    Register the service as keyed (AddKeyedScoped/AddKeyedSingleton/AddKeyedTransient). The .NET 8.0.9 opt-out switch doesn’t exist in .NET 9.
    Why it’s rare (our view)
    Needs keyed DI with a missing registration; apps on patched .NET 8 (8.0.9+) already have this behavior.

    Microsoft’s page for this change

  • .NET 9InteropBinary incompatibleCET supported by defaultapphost and singlefilehost are marked Intel CET-compatible. Loaded native libraries that set thread context to locations not on the shadow stack cause process termination.
    How to tell
    Process terminated when a native library that manipulates thread context is loaded (Windows hardware-enforced stack protection).
    What to do
    Opt out with <CETCompat>false</CETCompat> in the project file, or exclude the app via Windows Security exploit protection/group policy.
    Why it’s rare (our view)
    Only Windows hosts using an apphost executable with unusual native libraries are affected.

    Microsoft’s page for this change

  • .NET 9CryptographyBehavioral changeWindows private key lifetime simplifiedOn Windows, when a PFX loads without PersistKeySet or EphemeralKeySet, private-key lifetime is now always tied to the X509Certificate2 instance produced directly from the load.
    How to tell
    Windows code that imports PFX files via X509Certificate2Collection.Import and relied on disposing a clone to erase the key.
    What to do
    If you relied on disposing a clone to erase the key, also (or instead) dispose the original loaded certificate object.
    Why it’s rare (our view)
    Only Windows/IIS apps with specific PFX collection-loading and disposal patterns are affected.

    Microsoft’s page for this change

  • .NET 10Core .NET librariesBehavioral change.NET runtime no longer provides default termination signal handlersThe runtime no longer installs default SIGTERM (Unix) or CTRL_SHUTDOWN/CTRL_CLOSE (Windows) handlers, so without other handlers the process exits immediately and ProcessExit isn’t raised.
    How to tell
    Code relying on AppDomain.ProcessExit or AssemblyLoadContext.Unloading during container/service shutdown in apps that don’t use the generic host.
    What to do
    Typical ASP.NET apps and hosts using UseConsoleLifetime need nothing. Otherwise register handlers with PosixSignalRegistration.Create.
    Why it’s rare (our view)
    ASP.NET Core and Generic Host workers register their own signal handlers; only hand-rolled console workers are affected.

    Microsoft’s page for this change

  • .NET 10Core .NET librariesBehavioral changeLDAP DirectoryControl parsing is now more stringentDirectoryControl parsing in System.DirectoryServices.Protocols moved to managed code and is stricter (ASN.1 tags, lengths, no trailing data, invalid UTF-8 throws), consistent across platforms.
    How to tell
    LdapConnection.SendRequest/EndSendRequest exceptions against non-compliant LDAP servers; EncoderFallbackException from the VlvRequestControl constructor.
    What to do
    Make sure the LDAP server complies with the RFCs; handle EncoderFallbackException when calling the VlvRequestControl constructor.
    Why it’s rare (our view)
    Only apps using System.DirectoryServices.Protocols against non-compliant servers are affected.

    Microsoft’s page for this change

  • .NET 10Core .NET librariesBehavioral changeIn .NET 8.0.32Named mutexes default to user scope on UnixNamed mutexes on Unix now default to per-user scope and storage (servicing change in 8.0.32, 9.0.21, 10.0.13). Creation fails for UIDs without a user-database entry.
    How to tell
    Named Mutex constructors on Linux; cross-user mutex sharing stops working; failures in containers run with docker run -u <uid> or Kubernetes runAsUser.
    What to do
    For cross-user access pass NamedWaitHandleOptions.None or set System.Threading.Mutex.UnsafeDefaultMutexScopeGlobal; in containers set XDG_RUNTIME_DIR or add a user.
    Why it’s rare (our view)
    Named mutexes are uncommon in web apps, but the arbitrary-UID container failure mode is worth noting.

    Microsoft’s page for this change

  • .NET 10CryptographyBehavioral change.NET 10 requires OpenSSL 1.1.1 or later on UnixOn Unix platforms where .NET uses OpenSSL (such as Linux), OpenSSL 1.1.1 or later is required; otherwise the app fails to start. macOS isn’t affected.
    How to tell
    App fails to start on an old Linux distribution or custom base image that has only OpenSSL older than 1.1.1.
    What to do
    Use a Linux or Unix distribution that includes OpenSSL 1.1.1 or later.
    Why it’s rare (our view)
    Current distros and official images ship OpenSSL 1.1.1 or 3.x; only very old custom base images are affected.

    Microsoft’s page for this change

  • .NET 10CryptographyBehavioral changeEnvironment variable renamed to DOTNET_OPENSSL_VERSION_OVERRIDEThe Linux setting CLR_OPENSSL_VERSION_OVERRIDE, which picks the preferred OpenSSL library version, is renamed to DOTNET_OPENSSL_VERSION_OVERRIDE.
    How to tell
    CLR_OPENSSL_VERSION_OVERRIDE set in Dockerfiles, Kubernetes manifests or host environment.
    What to do
    Use DOTNET_OPENSSL_VERSION_OVERRIDE instead of CLR_OPENSSL_VERSION_OVERRIDE.
    Why it’s rare (our view)
    Few deployments pin the OpenSSL version through this variable.

    Microsoft’s page for this change

  • .NET 10GlobalizationBehavioral changeEnvironment variable renamed to DOTNET_ICU_VERSION_OVERRIDEThe Linux setting CLR_ICU_VERSION_OVERRIDE, which picks the preferred ICU library version, is renamed to DOTNET_ICU_VERSION_OVERRIDE.
    How to tell
    CLR_ICU_VERSION_OVERRIDE set in Dockerfiles, Kubernetes manifests or host environment.
    What to do
    Use DOTNET_ICU_VERSION_OVERRIDE instead of CLR_ICU_VERSION_OVERRIDE.
    Why it’s rare (our view)
    Few deployments pin the ICU version through this variable.

    Microsoft’s page for this change

  • .NET 10NetworkingBehavioral changeUri length limits removedUri constructors and TryCreate no longer cap URI strings at about 65,000 characters; paths, queries and fragments can be practically unlimited.
    How to tell
    Input validation that relied on new Uri(…) or Uri.TryCreate failing for very long strings.
    What to do
    If you relied on Uri for length validation, check lengths yourself before constructing the Uri.
    Why it’s rare (our view)
    Few apps rely on Uri’s length cap for validation, but those that did lose a safeguard silently.

    Microsoft’s page for this change

  • .NET 10SDK and MSBuildSource incompatibleNuGet packages with no runtime assets aren't included in deps.jsonPackages or libraries contributing no runtime assets may be dropped from deps.json if removing them doesn’t break dependency paths.
    How to tell
    Tools or security scanners that read the app’s deps.json and expect every referenced package to be listed.
    What to do
    To keep the old behavior, set the MSBuild property TrimDepsJsonLibrariesWithoutAssets to false.
    Why it’s rare (our view)
    The runtime is unaffected; only tooling that inspects deps.json notices.

    Microsoft’s page for this change

ASP.NET Core · 4

  • ASP.NET Core 9Behavioral changeDefaultKeyResolution.ShouldGenerateNewKey altered meaningData Protection’s DefaultKeyResolution.ShouldGenerateNewKey no longer signals that the default key is near expiry; it now means no default key or a policy reason.
    How to tell
    Custom IDefaultKeyResolver implementations or code reading DefaultKeyResolution.ShouldGenerateNewKey.
    What to do
    Remove replicated expiry logic from custom resolvers (optional); check the default key’s ExpirationDate directly instead.
    Why it’s rare (our view)
    Only custom Data Protection key resolvers or code consuming this internal-namespace API.

    Microsoft’s page for this change

  • ASP.NET Core 9Behavioral changeIn .NET 8.0.10Dev cert export no longer creates folderdotnet dev-certs https export no longer creates a missing target directory; the export fails instead.
    How to tell
    There was an error exporting the HTTPS developer certificate to a file. when running dotnet dev-certs https -ep to a non-existent folder (for example in dev scripts).
    What to do
    Create the target directory, with appropriate permissions, before running dotnet dev-certs.
    Why it’s rare (our view)
    Only dev/CI scripts that export the dev cert into a folder that doesn’t exist yet; first appeared in .NET 8.0.10 too.

    Microsoft’s page for this change

  • ASP.NET Core 10Source incompatibleIncludeOpenAPIAnalyzers property and MVC API analyzers are deprecatedSetting IncludeOpenAPIAnalyzers to true now emits warning ASPDEPR007; the MVC API analyzers still work but will be removed in a future release.
    How to tell
    Warning ASPDEPR007 from projects with <IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>.
    What to do
    Remove the IncludeOpenAPIAnalyzers property and migrate to TypedResults; or suppress ASPDEPR007 via NoWarn temporarily.
    Why it’s rare (our view)
    Opt-in MSBuild property that few projects set.

    Microsoft’s page for this change

  • ASP.NET Core 10Source incompatibleMicrosoft.Extensions.ApiDescription.Client package deprecatedThe Microsoft.Extensions.ApiDescription.Client package is deprecated; referencing projects get build warnings and its OpenApiReference MSBuild targets and dotnet openapi CLI are no longer supported.
    How to tell
    PackageReference to Microsoft.Extensions.ApiDescription.Client, <OpenApiReference> items, OpenApiProjectReference, or dotnet openapi commands.
    What to do
    Remove the package; generate clients with NSwag, Kiota or OpenAPI Generator tooling, committing output or using a custom pre-build step.
    Why it’s rare (our view)
    Only apps generating OpenAPI clients at build time via OpenApiReference.

    Microsoft’s page for this change

EF Core · 12

  • EF Core 9Medium impactMicrosoft.EntityFrameworkCore.Design not found when using EF toolsWith .NET SDK 9.0.200+, EF tools can fail to load Microsoft.EntityFrameworkCore.Design when it is referenced as a private asset; Microsoft says EF Core 10 fixes it.
    How to tell
    ‘Could not load file or assembly Microsoft.EntityFrameworkCore.Design...’ when running dotnet ef or PMC tools.
    What to do
    Until you’re on EF Core 10, add <Publish>true</Publish> to the Design PackageReference (the DLL is then copied to the output and publish folders).
    Why it’s rare (our view)
    Microsoft rates it Medium but says EF Core 10 fixes it, so a direct move to EF Core 10 shouldn’t hit it. It matters only if you stop on EF Core 9 with SDK 9.0.200 or later.

    Microsoft’s page for this change

  • EF Core 9Low impactToString() method now returns empty string for null instancesIn queries, ToString() on a null value now consistently returns an empty string; previously results varied (null, “True”, or empty) by type and context.
    How to tell
    LINQ queries calling ToString() on nullable properties (for example bool?) whose results now come back as empty string instead of null.
    What to do
    Rewrite the query with an explicit null check, for example x.NullableBool == null ? null : x.NullableBool.ToString().
    Why it’s rare (our view)
    Microsoft rates it Low; only queries projecting ToString() of nullable values.

    Microsoft’s page for this change

  • EF Core 9Low impactSQL Server IndexOf now propagates null valuesOn SQL Server, IndexOf on a null string now returns null rather than 0 (for empty search strings), matching SQLite.
    How to tell
    SQL Server queries using string.IndexOf on nullable string columns.
    What to do
    Handle null explicitly in the query, for example e.NullableString == null ? 0 : e.NullableString.IndexOf(...).
    Why it’s rare (our view)
    Microsoft rates it Low; narrow query pattern.

    Microsoft’s page for this change

  • EF Core 9Low impactCompiled models now reference value converter methods directlyCompiled models (dotnet ef dbcontext optimize) now generate code calling value converter methods directly, so private conversion methods cause compilation failures.
    How to tell
    Build errors in generated compiled-model code after dotnet ef dbcontext optimize, when a ValueConverter uses private static methods.
    What to do
    Make methods referenced by value converters public or internal.
    Why it’s rare (our view)
    Microsoft rates it Low; only apps using compiled models with custom converters.

    Microsoft’s page for this change

  • EF Core 9Low impactEF.Constant() and EF.Parameter() no longer work inside compiled queriesUsing EF.Constant or EF.Parameter inside EF.CompileQuery/CompileAsyncQuery now throws an InvalidCastException.
    How to tell
    InvalidCastException ‘Unable to cast object of type System.Linq.Expressions.ConstantExpression to type System.Linq.Expressions.ParameterExpression’.
    What to do
    Remove EF.Constant/EF.Parameter from the compiled query, or stop compiling that query.
    Why it’s rare (our view)
    Microsoft rates it Low; needs both compiled queries and EF.Constant/EF.Parameter.

    Microsoft’s page for this change

  • EF Core 9Low impactSome NoTrackingWithIdentityResolution queries are now prohibited for JSON collectionsEF Core 9 throws for some AsNoTrackingWithIdentityResolution queries over JSON-mapped collections, including LINQ operators applied directly to JSON collection navigations.
    How to tell
    Exceptions from AsNoTrackingWithIdentityResolution (or NoTrackingWithIdentityResolution) queries that use OrderBy, Where, Skip or Take on JSON collection navigations.
    What to do
    Use a tracking query if identity resolution is needed; otherwise use AsNoTracking.
    Why it’s rare (our view)
    Microsoft rates it Low; needs JSON columns plus identity-resolution no-tracking queries.

    Microsoft’s page for this change

  • EF Core 9Low impactEF.Functions.Unhex() now returns byte[]?EF.Functions.Unhex() (SQLite) is now annotated as returning byte[]? because SQLite returns NULL for invalid input.
    How to tell
    New nullable-reference warnings where EF.Functions.Unhex() results are used.
    What to do
    Add the null-forgiving operator if inputs are always valid hex; otherwise add null checks.
    Why it’s rare (our view)
    Microsoft rates it Low; SQLite-only function, compile-time nullability warning.

    Microsoft’s page for this change

  • EF Core 10Low impactApplication Name is now injected into the connection stringEF now adds an Application Name to SQL Server connection strings lacking one, so mixed EF and ADO.NET/Dapper access in TransactionScope may escalate to distributed transactions.
    How to tell
    Unexpected distributed-transaction escalation, or separate connection pools, when EF and Dapper/ADO.NET share a database inside a TransactionScope.
    What to do
    Define an Application Name in your connection string; EF then leaves it unchanged.
    Why it’s rare (our view)
    Microsoft rates it Low; edge case needing mixed data access inside TransactionScope.

    Microsoft’s page for this change

  • EF Core 10Low impactExecuteUpdateAsync now accepts a regular, non-expression lambdaExecuteUpdate/ExecuteUpdateAsync column setters are now a Func rather than an Expression, so hand-built setter expression trees no longer compile.
    How to tell
    Compile errors where code builds Expression<Func<SetPropertyCalls<T>, SetPropertyCalls<T>>> for ExecuteUpdate.
    What to do
    Rewrite as a statement lambda that calls SetProperty conditionally.
    Why it’s rare (our view)
    Microsoft rates it Low; only code that builds setter expression trees dynamically.

    Microsoft’s page for this change

  • EF Core 10Low impactComplex type column names are now uniquifiedWhen properties in different complex types map to the same column name, EF now appends a number instead of silently sharing one column.
    How to tell
    Unexpected migrations renaming/adding columns for complex types with clashing column names.
    What to do
    To share a column intentionally, configure each property explicitly with HasColumnName.
    Why it’s rare (our view)
    Microsoft rates it Low; complex types (EF 8+) with colliding column names.

    Microsoft’s page for this change

  • EF Core 10Low impactNested complex type properties use full path in column namesProperties of nested complex types now map to columns named with the full path (Complex_NestedComplex_Property) instead of NestedComplex_Property.
    How to tell
    Migrations renaming columns for nested complex type properties after upgrading.
    What to do
    Keep old names by configuring them explicitly with HasColumnName.
    Why it’s rare (our view)
    Microsoft rates it Low; only models with nested complex types.

    Microsoft’s page for this change

  • EF Core 10High impactWriting DateTimeOffset into REAL column now writes in UTCMicrosoft.Data.Sqlite 10 converts DateTimeOffset values to UTC before writing them to REAL columns; previously the offset was ignored.
    How to tell
    SQLite apps storing DateTimeOffset in REAL columns; newly written values differ from older rows.
    What to do
    Adjust code; as a temporary last resort set the Microsoft.Data.Sqlite.Pre10TimeZoneHandling AppContext switch to true.
    Why it’s rare (our view)
    Microsoft rates it High, but needs SQLite plus DateTimeOffset stored in REAL columns.

    Microsoft’s page for this change

What this page leaves out

124 of the 194 entries on Microsoft’s lists aren’t here. Each list as it stood on 25 October 2026, with the day Microsoft last updated it:

ListListedHereOut of scopeUpdated
.NET 9611410 for Windows Forms and WPF
.NET 1080218 for Windows Forms and WPF
ASP.NET Core 9651 for Blazor WebAssembly only
ASP.NET Core 1099None
EF Core 924910 for the Azure Cosmos DB provider
EF Core 101412None

Sources

Microsoft’s six lists, each read in full on the day shown. Every entry above links to its own change page, checked the same day.

About this page

Updated
Verified
25 Oct 2026

Cite this page

SnowDriven. “.NET 8 to .NET 10: the breaking changes that hit web apps.” SnowDriven Research. https://snowdriven.com/research/net-10-breaking-changes/ (last updated 25 October 2026).

One click or tap selects the whole citation, ready to copy.

About these facts

Each entry summarizes Microsoft’s own page for that change, linked and checked on the day shown; the likely, possible and rare ratings, and the reasons for them, are ours. Microsoft can change its lists and pages without notice, and our summary can fall behind or contain mistakes, so read the linked page before you change a system. Information only, provided as is (terms). Reuse: free to quote, with credit to SnowDriven and a link (terms of use).

Start a project

Want this list checked against your code?

We can go through your solution with it: which entries apply, what each takes to fix, and the order to move services in. Tell us what you run and where it’s hosted; we reply within one business day.

Pittsburgh, PA · Since 2015 · First step: a 30-minute call