MySQL

How to Resolve "Incorrect String Value" UTF8 Encoding Error in MySQL

4 min read by DebuggedIt

Quick answer

Inserting text containing emoji, certain non-Latin characters, or specific Unicode symbols fails with an encoding error, even though your table is already...

Inserting text containing emoji, certain non-Latin characters, or specific Unicode symbols fails with an encoding error, even though your table is already configured for UTF-8. This almost always means you're using MySQL's legacy utf8 character set, which is actually a 3-byte-max subset that can't represent everything real UTF-8 can β€” you need utf8mb4 instead.

The Problem

A normal-looking insert fails on specific characters:

mysql> INSERT INTO messages (content) VALUES ('Great job! πŸŽ‰');
ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x8E\x89' for column 'content' at row 1

It also shows up with certain CJK (Chinese/Japanese/Korean) characters and other symbols outside the Basic Multilingual Plane:

ERROR 1366 (HY000): Incorrect string value: '\xF0\xA0\x9C\x8E...' for column 'name' at row 1

Why It Happens

MySQL's character set named utf8 is historically limited to a maximum of 3 bytes per character, which covers the vast majority of common text but excludes characters that require 4 bytes in true UTF-8 encoding β€” this includes most emoji, some rarer CJK ideographs, and a handful of other Unicode ranges. True UTF-8 supports up to 4 bytes per character, which MySQL implements under the separate name utf8mb4 (the "mb4" stands for "max bytes 4"). This confusing naming is a legacy decision MySQL has never fully undone, and it trips up a huge number of people who reasonably assume utf8 means the same thing MySQL's docs call utf8mb4. The error appears when:

  • A table or column was created with CHARACTER SET utf8 instead of utf8mb4, so 4-byte characters simply can't be stored.
  • The table is correctly utf8mb4, but the client connection itself is still negotiating as utf8, causing the same truncation before the data even reaches the table definition.
  • An older MySQL client library or ORM defaults to utf8 for backward compatibility and needs to be explicitly told to use utf8mb4.

The Fix

Check your table and column's current character set:

SHOW CREATE TABLE messages;
CREATE TABLE `messages` (
  `content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Convert the table and all its text columns to utf8mb4:

ALTER TABLE messages CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

For the whole database, so any new tables default correctly:

ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Confirm the change actually applied:

SHOW CREATE TABLE messages;
CREATE TABLE `messages` (
  `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Just as important, make sure the client connection itself uses utf8mb4 too, or you'll hit the same error even with a correctly configured table. In application connection strings:

# MySQL connection string example
mysql://user:pass@localhost/mydb?charset=utf8mb4

Or explicitly at the start of a session:

SET NAMES utf8mb4;

In the MySQL server config, set the default for new connections and databases going forward:

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

Still Not Working?

If existing rows were already truncated or mangled by the old utf8 encoding before you converted the schema, converting the column type alone won't recover lost data β€” anything that failed to insert never made it into the table, and anything that inserted silently with a fallback character may be corrupted in place. Check for suspicious replacement characters in existing data:

SELECT id, content FROM messages WHERE content LIKE '%?%' OR content LIKE '%\uFFFD%';

Rows matching that pattern may need to be re-imported from an original source if one exists, since the character data itself may be unrecoverable from what's currently stored in MySQL.

It's also worth checking your application framework or ORM's default configuration, since many older frameworks and libraries still default to utf8 for backward compatibility even on recent MySQL versions, silently reintroducing this exact problem even after you've fixed the database schema itself. Explicitly configuring utf8mb4 at every layer β€” the table definition, the database default, and the client connection β€” is the only way to be confident the whole chain is consistent:

# Example: Laravel database config
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
# Example: Django settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}

For any project still on an older MySQL version (5.5 or earlier), note that utf8mb4 support and the more space-efficient utf8mb4_unicode_ci collation weren't fully available until MySQL 5.5.3, and some subtleties around index key length limits with 4-byte characters weren't resolved until 5.7's default innodb_large_prefix behavior β€” upgrading MySQL itself may be a prerequisite step if you're hitting related index length errors after switching the character set.