SYSTEMS OPERATIONAL
Troubleshooting

WordPress Showing Garbled Text? Fix the Charset Mismatch

Getwebup 7 min read

You migrated a site, restored a backup, or imported a database dump, and now half your content looks like garbage — emoji show up as question marks, accented names turn into boxes, and sometimes a form submission just fails outright with a MySQL error about an "incorrect string value." Nine times out of ten, this is a charset and collation mismatch, and it's one of the more misunderstood problems in WordPress hosting.

The Symptom: Question Marks, Boxes, or a Hard Failure

There are two flavors of this bug, and which one you get tells you something about the cause.

  • Silent corruption — text that used to say "café" now shows "caf?" or "café" (mojibake). This usually means the data was already stored wrong, or it's being read with the wrong connection charset.
  • Hard error on save — you try to publish a post with an emoji or a name like "Zoë" and WordPress throws something like: WordPress database error: Incorrect string value: '\xF0\x9F\x98\x80...' for column 'post_content'. This means the column itself can't physically store that character.

Both trace back to the same root cause: somewhere between your application, your database connection, and your table definition, there's a charset that can't represent the characters you're feeding it.

Why This Happens: utf8 Is Not Actually UTF-8

This is the part that trips people up. MySQL has a charset literally named utf8, and it is not full UTF-8 — it only supports characters up to 3 bytes. Emoji, many CJK characters, and some symbols need 4 bytes, and MySQL's utf8 simply can't hold them. The real full-Unicode charset is called utf8mb4 ("utf8, max 4 bytes"), and WordPress has defaulted new installs to it since version 4.2 (2015).

So the classic failure pattern is:

  1. A site was created years ago, or migrated from an old host, on tables using utf8 / utf8_general_ci.
  2. It gets moved to a newer server (like a fresh Getwebup VPS or cPanel account) where MySQL/MariaDB defaults are utf8mb4.
  3. The export/import step, or wp-config.php, or the live tables end up mismatched — some pieces think utf8mb4, others think utf8 — and reads/writes start clashing.

Collation is the second half of the puzzle. Two columns can both be "utf8mb4" but use different collations — say utf8mb4_general_ci vs utf8mb4_unicode_520_ci vs (on MySQL 8) utf8mb4_0900_ai_ci. Mixed collations between joined tables or between a query's comparison values throw errors like Illegal mix of collations, which is a close cousin of this same problem.

Check What You're Actually Running

Before changing anything, find out where the mismatch actually is. SSH in (or use cPanel's Terminal) and check from three angles.

1. What does wp-config.php claim?

grep -E "DB_CHARSET|DB_COLLATE" /home/USERNAME/public_html/wp-config.php

You want DB_CHARSET set to utf8mb4. DB_COLLATE is usually left blank — WordPress picks a sensible default collation itself.

2. What do the tables actually use? Log into phpMyAdmin (cPanel → Databases → phpMyAdmin) or the mysql client, and run:

SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_db_name';

If you see a mix — some tables utf8mb4_general_ci, others still utf8_general_ci or latin1_swedish_ci — that's your mismatch.

3. What charset does the connection itself negotiate? Run:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

Column-level charset wins over server defaults, but if the connection charset is wrong during an import, data can get mangled on the way in even if the destination column is correct — which is why re-importing with the right flags matters more than fixing columns after the fact.

The Fix

1. Fix wp-config.php first

Make sure it reads:

define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );

Leaving DB_COLLATE empty lets WordPress core choose the right collation for your MySQL/MariaDB version instead of hardcoding one that might not exist on this server.

2. Convert the database and tables

If your MySQL version is 5.6+ (nearly all current hosting is), you can convert in place. Back up the database first — this is a good moment to use cPanel's Backup Wizard or mysqldump before touching anything:

mysqldump -u USER -p your_db_name > pre_convert_backup.sql

Then convert the database default and every table:

ALTER DATABASE your_db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci;

ALTER TABLE wp_posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci;
ALTER TABLE wp_postmeta CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci;
ALTER TABLE wp_comments CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci;
-- repeat for every wp_* table, including plugin-created ones

If you'd rather not type this out table by table, WP-CLI can loop through the whole database in one shot:

wp db query "SELECT CONCAT('ALTER TABLE ', table_name, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci;') FROM information_schema.tables WHERE table_schema = DATABASE();" --skip-column-names | wp db query -

On MySQL 8 / recent MariaDB, utf8mb4_0900_ai_ci or utf8mb4_general_ci may be the better fit depending on what your version supports — check with SHOW COLLATION LIKE 'utf8mb4%'; if the exact collation name above errors out.

3. Watch for the "index too long" error

Because utf8mb4 uses up to 4 bytes per character versus 3 for utf8, converting can push some indexed columns (especially meta_key in wp_postmeta or wp_options) past MySQL's max index key length on older versions. If you hit Specified key was too long, you either need MySQL 5.7.7+/MariaDB 10.2.2+ with innodb_large_prefix enabled (default on modern versions), or you'll need to shorten the affected index — this is one case where it's worth asking your host to confirm the server's InnoDB settings before you fight it manually.

4. If data is already corrupted, converting won't fix it

This is the part people miss: CONVERT TO CHARACTER SET re-interprets bytes according to the declared charset. If the bytes were already mangled during a bad import (double-encoded, or truncated multi-byte characters), converting the column type won't un-corrupt them — you'll need to restore from a backup taken before the bad import and redo the migration correctly.

5. Redo the export/import with the right flags

For future migrations, always export and import specifying the charset explicitly so nothing gets silently re-encoded along the way:

mysqldump -u USER -p --default-character-set=utf8mb4 your_db_name > export.sql

mysql -u USER -p --default-character-set=utf8mb4 your_db_name < export.sql

If you're using phpMyAdmin's UI instead, set the "Character set of the file" to utf8mb4 on both the export and import screens — it defaults to plain utf8 on some installs, which is exactly how this problem starts.

Prevention Checklist

StepWhy it matters
Always use --default-character-set=utf8mb4 on mysqldump/mysqlPrevents re-encoding during export/import
Confirm DB_CHARSET is utf8mb4 in wp-config.php after every migrationMigrations sometimes copy an old config file
Test with an emoji or accented name right after migratingCatches the problem before real content gets corrupted
Keep table and database collation consistent across the whole DBAvoids "Illegal mix of collations" errors on joins
Take a backup before any ALTER TABLE / CONVERT operationConversion is not always reversible if something goes wrong mid-run

When to Just Call Support

If you're on Getwebup shared hosting or a managed VPS and don't want to run raw SQL against production, open a ticket with the database name and one example of the broken text (a screenshot works fine). We can check table collations, confirm what your MySQL/MariaDB version actually supports, and run the conversion safely with a backup in place first.

Frequently asked questions

Is utf8mb4 slower than utf8?

The practical difference is negligible for typical WordPress workloads. utf8mb4 uses up to 4 bytes per character instead of 3, which slightly increases storage for text-heavy columns, but query performance is not meaningfully affected. The compatibility you gain (emoji, full Unicode) is worth far more than the tiny storage overhead.

Why did my site work fine for years and only break now?

Usually because something changed the plumbing without you doing anything — a host migration, a WordPress core update, or a plugin update that started inserting emoji or special characters (reactions, WooCommerce product variants with accented names, etc.). The mismatch was often already there; it just wasn't being triggered until new content exposed it.

Can I convert just one table instead of the whole database?

Yes, but it usually creates more problems than it solves. WordPress tables reference each other constantly (posts to postmeta, comments to commentmeta), and mixed collations between joined tables cause 'Illegal mix of collations' errors. Convert the whole database and all wp_* tables together, including any created by plugins.

I ran the ALTER TABLE commands and now I'm getting 'Specified key was too long' — what now?

This means an indexed column can't fit the larger utf8mb4 character width under your MySQL version's index length limit. Check whether your server has innodb_large_prefix enabled and is running MySQL 5.7.7+/MariaDB 10.2.2+ (most current hosting is). If it's an older version, you'll need to shorten the index or ask your host to check the InnoDB file format settings.

My text still shows as question marks after converting the tables — why?

If the corruption happened during a prior import, the bad bytes are already stored in the database and converting the column type won't restore them — it can only reinterpret what's there. You'll need to restore a backup from before the bad import and re-run the migration using --default-character-set=utf8mb4 on both export and import.

#mysql #utf8mb4 #charset #collation #wordpress #database

Keep reading

Chat with Support