Cause
This seems to be caused by a bug in MySQL 8 when setting character_set_server to utf8 in the MySQL ([mysqld]) config.
The MySQL manual states:
MySQL immediately converts instances of utf8mb3 in statements to utf8,
so in statements such as SHOW CREATE TABLE or SELECT
CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLUMNS or SELECT
COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS, users see the name
utf8 or utf8_collation_substring.
However, the query SHOW VARIABLES LIKE 'character_set_server'; still returns
----------------------+----------+
| Variable_name | Value |
+----------------------+---------+
| character_set_server | utf8mb3 |
+----------------------+---------+
-> utf8mb3
The relevant part of the code in phpMyAdmin can be found in libraries/classes/Charsets.php:
/**
* Get current server charset
*
* @param DatabaseInterface $dbi DatabaseInterface instance
* @param bool $disableIs Disable use of INFORMATION_SCHEMA
*/
public static function getServerCharset(DatabaseInterface $dbi, bool $disableIs): Charset
{
if (self::$serverCharset !== null) {
return self::$serverCharset;
}
self::loadCharsets($dbi, $disableIs);
$serverCharset = $dbi->getVariable('character_set_server');
if (! is_string($serverCharset)) {// MySQL 5.7.8 fallback, issue #15614
$serverCharset = $dbi->fetchValue('SELECT @@character_set_server;');
}
self::$serverCharset = self::$charsets[$serverCharset];
return self::$serverCharset;
}
What phpMyAdmin is doing in the method getServerCharset in libraries/classes/Charsets.php (which is causing the error) is the following:
It checks whether it has already determined the charset. If not,
it loads an array of charsets available from the MySQL server with the method loadCharsets. This however is done either by the query SHOW CHARACTER SET; or by querying information_schema. In both cases, utf8 (instead of utf8mb3) is returned, as explained above in the MySQL manual.
Then, it gets the server charset with the query SHOW VARIABLES LIKE 'character_set_server'; (Here, utf8mb3 is returned as the result, as seen above).
There is a fallback (not relevant in our case) due to a bug in MySQL 5.7.8, which we can ignore.
It writes the result into the variable self::$serverCharset, by getting the array element with the key $serverCharset (which is utf8mb3) from the array of all server charsets available . As we know, there is no key utf8mb3 in the array of the available server charsets (only utf8 which is the alias for utf8mb3). Therefore, the error occurs.
How to fix it
To fix this, either MySQL should instead return utf8 on the query SHOW VARIABLES LIKE 'character_set_server';, which isn't something we can easily influence (a bug report might have to be created), or we have to work around it in the phpMyAdmin source code.
To do this, I added
if ($serverCharset === "utf8mb3") {
$serverCharset = "utf8";
}
before the line
self::$serverCharset = self::$charsets[$serverCharset];
so that it now looks like this:
/**
* Get current server charset
*
* @param DatabaseInterface $dbi DatabaseInterface instance
* @param bool $disableIs Disable use of INFORMATION_SCHEMA
*/
public static function getServerCharset(DatabaseInterface $dbi, bool $disableIs): Charset
{
if (self::$serverCharset !== null) {
return self::$serverCharset;
}
self::loadCharsets($dbi, $disableIs);
$serverCharset = $dbi->getVariable('character_set_server');
if (! is_string($serverCharset)) {// MySQL 5.7.8 fallback, issue #15614
$serverCharset = $dbi->fetchValue('SELECT @@character_set_server;');
}
if ($serverCharset === "utf8mb3") {
$serverCharset = "utf8";
}
self::$serverCharset = self::$charsets[$serverCharset];
return self::$serverCharset;
}
The error should not occur anymore.