Skip to main content

MY.L6.CHARACTER_SET_SERVER_NOT_UTF8MB4 — a default charset that quietly cannot hold your data

  • Category: safety
  • Level: 6
  • Confidence: deterministic
  • Downtime class: none
  • Stability: stable
  • Suites: audit
  • Applies to: MySQL 8.4
  • Not transferable to MariaDB: this page describes MySQL 8.4 behavior. MariaDB answers the same driver and does not share these semantics, so SQLens refuses it outright rather than reasoning about it — see drivers/unsupported.

A database or table created without an explicit CHARACTER SET takes the server's.

Laravel's schema builder does emit one for the tables it creates, from config('database.connections.mysql.charset'). So the common failure is not those tables — it is everything else:

  • a database an operator created by hand,
  • a table added by hand,
  • a temporary table,
  • a migration written in raw SQL.

On latin1 those objects cannot hold most of Unicode. Depending on the SQL mode, MySQL replaces the character or truncates the value at it rather than refusing the write. The row is stored, altered, and nobody finds out until somebody asks why their name is wrong.

utf8mb3 is the trap that looks solved

It is called out by name rather than lumped in with latin1. It is three bytes per character and covers only the Basic Multilingual Plane — so it holds most of what anyone tests with, and silently cannot store an emoji.

The name is the trap: it says utf8 and it is not.

Flagged

SET GLOBAL character_set_server = latin1;

Preferred

SET GLOBAL character_set_server = utf8mb4;

Why this is one rule and not two

collation_server is not a separate finding, because MySQL will not let the two disagree.

Measured on 8.4.10:

StatementEffect on the other variable
SET character_set_server = latin1collation_server became latin1_swedish_ci
SET collation_server = utf8mb4_unicode_cicharacter_set_server became utf8mb4

They are one setting with two names. A second rule would report the same misconfiguration twice under two ids — and an ignore-list entry for one would leave the other one shouting.

What is deliberately not judged

Which utf8mb4 collation the server carries. utf8mb4_0900_ai_ci and utf8mb4_unicode_ci are both legitimate, and the second pins an older Unicode version — a real reason on a database that has to keep sort order stable across a MySQL upgrade.

The charset is a correctness question. The collation within it is a decision.

Sources