An existing .NET Framework application moves from MySQL to MariaDB, and a connection or query now fails with a message like Character set 'utf8mb3' is not supported. Where should the investigation start?
My answer: with the connector that the running application actually loads, then the server's character set settings, and only after that the schema. Changing columns before you understand the failure can turn a dependency problem into a data migration.
This is a diagnostic guide built from official documentation, which I re-read on November 2, 2026. I did not reproduce the exception for this article, and the snippets below are diagnostics to adapt, not tested fixes.
Why the name utf8mb3 appears at all
Two documented facts fit together here.
The MariaDB OLD_MODE documentation says that from MariaDB 10.6.1, "the main name of the previous 3-byte utf8 character set was changed to utf8mb3". With the UTF8_IS_UTF8MB3 flag set, utf8 is an alias for utf8mb3. That flag was on by default until MariaDB 13.1, where the default changed and utf8 became an alias for utf8mb4.
The Connector/NET 8.0.28 release notes include this fix: "Connector/NET did not support the utf8mb3 character set" (Bug #105516, Bug #33556024).
So an application that still ships an older MySql.Data, connected to a MariaDB server that reports utf8mb3, is a concrete hypothesis worth testing first. It is a hypothesis, not a diagnosis. The same wording can come from other paths, and the evidence below is what confirms or rules it out.
Step 1: keep the whole failure
Save the full exception, inner exceptions and stack trace, with credentials removed. Note whether it fails when opening the connection, executing a command or reading results. Write down the .NET Framework target, the MariaDB version, the package references and what changed in the move.
Step 2: find the connector assembly that really loads
A package reference tells you what the project asks for. The deployed bin folder, the GAC or a binding redirect can give you something else. Log this from the running application through your normal logging path, never through a public endpoint:
var asm = typeof(MySql.Data.MySqlClient.MySqlConnection).Assembly; log.Info(asm.FullName); // name and version that actually loaded log.Info(asm.Location); // file that was loaded log.Info(asm.CodeBase); // original location before shadow copying Microsoft documents Assembly.Location as the location of the loaded file that contains the manifest. On .NET Framework, if the file was shadow-copied, Location points to the copy, and the same page says to use CodeBase for the location before shadow copying. ASP.NET copies Bin assemblies into its Temporary ASP.NET Files directory by default (shadowCopyBinAssemblies defaults to true), so a temporary path in Location is expected and not a sign of a bad deploy by itself.
If FullName shows a MySql.Data version below 8.0.28, you have a strong lead.
Step 3: check binding redirects and publisher policy
Microsoft's assembly redirection guide explains that the application configuration file, publisher policy and machine configuration can all redirect assembly versions.
Open the deployed web.config and look for the assemblyBinding entry for MySql.Data. Compare it with source control and with the release artifact. A redirect pinned to an old version, or a forgotten copy in the GAC, explains why updating the NuGet package changed nothing. Don't paste a redirect from a forum post: the right oldVersion range and newVersion depend on what the app actually references.
Step 4: capture the server's view
From an admin client, outside the failing app:
SELECT VERSION(); SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%'; The SHOW VARIABLES syntax accepts a LIKE 'pattern' with % wildcards. Then check the affected tables. The MariaDB character set page uses both of these:
SHOW CREATE TABLE your_table\G SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'your_db'; Don't infer each column from one server variable. Record what you see next to the exception and the loaded connector version.
Step 5: make one bounded change
If the evidence points to an old Connector/NET, the smallest change is updating MySql.Data to a version that includes the 8.0.28 fix and that still supports your framework target, then fixing the redirect so that version is the one that loads. Do it in a branch, deploy to staging, log the loaded assembly again and repeat the failing operation. Keep schema changes out of this experiment so the result means something.
Switching providers is a different, bigger scope. The MySqlConnector migration guide says to change using MySql.Data.MySqlClient; to using MySqlConnector;, and that MySqlClientFactory is named MySqlConnectorFactory, which matters if the app uses DbProviderFactories. Its connection options also change behavior: MySqlConnector "always uses utf8mb4" and ignores CharacterSet, ConnectionReset defaults to true, and IgnoreCommandTransaction defaults to false. Audit those against the app's code and ORM before calling it a drop-in replacement.
Converting stored data to utf8mb4 is a third decision with its own risks, such as index length limits and table rebuilds. It does not belong in the same change, and it needs a rehearsal on a restored copy.
Step 6: verify and keep a way back
Before touching anything, define the checks: the original failing operation, a round trip of text with accents and emoji, and the main user flow that hit the error. Keep the previous artifact and configuration so rolling back is a redeploy, and after a rollback check startup and the loaded assembly again.
The useful outcome is a short chain of evidence: the failing operation, the connector that loaded, the redirect, what the server reports, one change and its measured result.
If you have an older .NET Framework or ASP.NET MVC app with a problem like this, I offer a fixed-scope diagnosis and fix on Upwork: https://www.upwork.com/services/product/2117249840584640174
