MySQL ERROR 1366 occurs when data cannot be stored in a column due to character set mismatches, type incompatibility, or invalid values. This commonly happens with UTF-8 special characters in latin1 columns, empty strings in integer columns, or numeric precision issues in strict mode.
MySQL ERROR 1366 is a data validation error that occurs when the database server rejects a value being inserted or updated because it cannot be stored in the target column. This error typically means that MySQL detects an incompatibility between the incoming data and the column's defined characteristics (character set, data type, or constraints). The error manifests differently depending on the root cause: - **Character set mismatch**: When UTF-8 data (especially emojis or special characters) is being stored in a latin1 or utf8 (3-byte only) column - **Type mismatch**: When non-numeric data is being inserted into numeric columns (INT, DECIMAL, etc.) - **Invalid values**: When invalid dates, out-of-range numbers, or truncated data conflict with column definitions In strict SQL mode (the default in MySQL 8.0+), this error stops the operation entirely. In non-strict mode, MySQL may silently truncate or convert the value, which can mask data corruption.
The error message contains crucial details. Look for patterns like:
- "Incorrect integer value: ''" - empty string in a numeric column
- "Incorrect string value: '\xF0\x9F\x94\x8D'" - unparseable bytes in the column charset
- "Incorrect value: '2024-13-45'" - invalid date/time format
-- The error typically appears in your MySQL error log or application error output
-- Example: ERROR 1366 (HY000): Incorrect integer value: '' for column 'user_id' at row 5Note which column is failing and what value was rejected. This tells you whether you're facing a character set issue, type issue, or data validation issue.
Check what character set your database, tables, and columns actually use. Many legacy systems use latin1 which cannot store UTF-8 properly.
-- Check database charset
SELECT schema_name, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE schema_name = 'your_database';
-- Check table charset
SHOW CREATE TABLE your_table;
-- Check specific column charset
SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'your_database' AND TABLE_NAME = 'your_table';If you see "latin1", "utf8" (not utf8mb4), or "ascii", these are the likely culprits. Modern MySQL should use utf8mb4 to support all Unicode characters including emojis.
utf8mb4 is the only MySQL charset that properly implements full UTF-8 encoding. It supports all Unicode characters (including 4-byte ones like emojis) and is the default in MySQL 8.0+.
-- Convert entire database to utf8mb4
ALTER DATABASE your_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Convert specific table (do this for each table that needs it)
ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Verify the conversion succeeded
SHOW CREATE TABLE your_table;This is a one-time operation. For large tables, it may take time and temporarily lock the table. Consider running during maintenance windows. Backup your database first!
Even if your database uses utf8mb4, your application's connection must also use the same character set. Otherwise, data gets corrupted during transmission.
// Node.js / mysql2
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydb',
charset: 'utf8mb4', // Important!
});
// Or set after connecting
connection.query("SET NAMES utf8mb4");# Python / mysql-connector-python
import mysql.connector
conn = mysql.connector.connect(
host="localhost",
user="root",
password="password",
database="mydb",
charset="utf8mb4", # Important!
collation="utf8mb4_unicode_ci"
)// PHP / MySQLi
$conn = new mysqli("localhost", "root", "password", "mydb");
$conn->set_charset("utf8mb4");Always match your application's connection charset to your database charset.
If you're importing data (CSV, SQL dumps) and hitting ERROR 1366 on numeric columns with empty values, use data cleansing techniques.
-- When importing with LOAD DATA INFILE, use NULLIF to convert empty strings to NULL
LOAD DATA INFILE '/path/to/data.csv'
INTO TABLE your_table
FIELDS TERMINATED BY ','
(column1, @user_id_raw, column3)
SET user_id = NULLIF(TRIM(@user_id_raw), '');# Or pre-process CSV data with sed/awk to remove empty fields
# Replace empty numeric fields with 0 or NULL
sed 's/,,,/,0,0,/' data.csv > data_cleaned.csvIn your application code, validate numeric inputs before sending to MySQL:
// Node.js example
const userId = input.user_id?.trim() || null;
if (userId && isNaN(userId)) {
throw new Error('user_id must be numeric or empty');
}
await db.query('INSERT INTO users (user_id) VALUES (?)', [userId]);Strict SQL Mode vs. Lenient Mode: In strict mode (default in MySQL 5.7+), ERROR 1366 is thrown immediately. In lenient mode, MySQL truncates or converts the value and issues a warning instead. For data integrity, always use strict mode.
utf8 vs. utf8mb4 Confusion: MySQL's "utf8" charset is NOT true UTF-8βit only supports 3-byte characters. It cannot store emojis or other 4-byte Unicode sequences. Use utf8mb4 for full Unicode support. Many developers waste hours debugging this.
Collation Implications: When changing charset, also update collation (utf8mb4_unicode_ci for case-insensitive, utf8mb4_bin for binary). Wrong collation can affect sorting and comparisons.
Large Table Conversions: Converting a 1GB+ table to utf8mb4 may lock it for extended periods. Use online DDL tools (Percona Toolkit, pt-online-schema-change) for zero-downtime migrations on production systems.
Backward Compatibility: If you're supporting legacy systems that send latin1-encoded data, consider a middleware layer that re-encodes data to utf8mb4 before inserting. This is safer than converting your entire database.
EE_WRITE (3): Error writing file
How to fix "EE_WRITE (3): Error writing file" in MySQL
CR_PARAMS_NOT_BOUND (2031): No data supplied for parameters
How to fix "CR_PARAMS_NOT_BOUND (2031): No data supplied for parameters" in MySQL
CR_DNS_SRV_LOOKUP_FAILED (2070): DNS SRV lookup failed
How to fix "CR_DNS_SRV_LOOKUP_FAILED (2070): DNS SRV lookup failed" in MySQL
ERROR 1146: Table 'database.table' doesn't exist
How to fix "ERROR 1146: Table doesn't exist" in MySQL
ERROR 1040: Too many connections
How to fix "ERROR 1040: Too many connections" in MySQL