How to Fix MySQL Error 1118: Row Size Too Large

ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs is raised when the combined fixed-length storage of all columns in a table definition exceeds MySQL's row size limits. The error symbol is ER_TOO_BIG_ROWSIZE.

Impact

This error is raised at DDL time — specifically during CREATE TABLE or ALTER TABLE — and prevents the statement from completing. No table is created (or modified) and no data is affected. The error surfaces in application code whenever a migration or schema change is attempted: Rails migrations, Flyway/Liquibase scripts, Django makemigrations, and any ORM that issues CREATE TABLE or ADD COLUMN will all surface this as a fatal exception.

There are two distinct limits in play. The MyISAM/generic MySQL limit is 65,535 bytes per row, shared across all columns (excluding BLOB/TEXT). The InnoDB-specific limit is stricter: with the default COMPACT or REDUNDANT row formats and a 16 KB page size, the fixed in-page portion of a row cannot exceed approximately 8,126 bytes. Rows that exceed the in-page limit require InnoDB to store column data off-page, but this only applies to variable-length columns (VARCHAR, VARBINARY, TEXT, BLOB) with the DYNAMIC or COMPRESSED row formats.

Common Causes

  1. Too many or too wide VARCHAR columns. A VARCHAR(255) using utf8mb4 consumes up to 4 bytes per character — 1,020 bytes of potential storage each. Ten such columns push the fixed row size past 10,000 bytes, exceeding the InnoDB in-page limit.

  2. Using COMPACT or REDUNDANT row format with large variable-length columns. These older row formats store the first 768 bytes of each variable-length column in-page. Numerous wide VARCHAR columns can easily exhaust the 8,126-byte in-page budget even before the 65,535 global limit is hit.

  3. Over-engineered schemas with many string columns. Schemas generated by code (e.g., EAV-style attribute tables, or wide analytics tables with dozens of text columns) may hit this limit during initial table creation.

  4. Migrating from Latin1 to utf8mb4. Converting a table's character set from latin1 (1 byte/char) to utf8mb4 (up to 4 bytes/char) multiplies the declared row size for VARCHAR columns by up to four, which can push a previously valid schema over the limit.

  5. Using ALTER TABLE ADD COLUMN on an already-wide table. Adding a new VARCHAR or CHAR column to a table that is already near the row size limit will trigger this error.

Troubleshooting and Resolution Steps

  1. Identify the column sizes contributing to the row size. Inspect the table definition and calculate approximate row width:

    SELECT
      column_name,
      data_type,
      character_maximum_length,
      character_set_name,
      CASE
        WHEN character_set_name = 'utf8mb4' THEN character_maximum_length * 4
        WHEN character_set_name IN ('utf8', 'utf8mb3') THEN character_maximum_length * 3
        ELSE character_maximum_length
      END AS max_bytes
    FROM information_schema.columns
    WHERE table_schema = 'your_db'
      AND table_name = 'your_table'
    ORDER BY max_bytes DESC;
    
  2. Switch to DYNAMIC row format. This is the most common fix. With DYNAMIC, variable-length columns exceeding 40 bytes are stored fully off-page, eliminating the in-page 768-byte prefix overhead:

    ALTER TABLE your_table ROW_FORMAT=DYNAMIC;
    

    Or set it at creation time:

    CREATE TABLE your_table (
      ...
    ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
    

    Ensure innodb_file_format is Barracuda (MySQL 5.6/5.7) or confirm MySQL 8.0+ (which uses Barracuda by default).

  3. Change large VARCHAR columns to TEXT or BLOB. TEXT and BLOB columns are always stored off-page (in MySQL's terms, they do not count against the 65,535-byte row limit). This is appropriate for columns that routinely hold large content:

    ALTER TABLE your_table
      MODIFY COLUMN description TEXT,
      MODIFY COLUMN notes MEDIUMTEXT;
    
  4. Reduce declared column widths. If VARCHAR(255) was used as a default but the actual data is much shorter, reducing the declared length decreases the calculated row size:

    ALTER TABLE your_table
      MODIFY COLUMN status VARCHAR(32),
      MODIFY COLUMN country_code VARCHAR(3);
    
  5. Normalize the schema. If the table has dozens of string columns, consider splitting it into a core table and one or more extension tables joined by primary key. This is particularly effective for EAV-style schemas.

  6. Check and adjust InnoDB page size. The default InnoDB page size is 16 KB. Larger page sizes (32 KB or 64 KB) increase the in-page row budget proportionally, though this requires recreating the InnoDB instance and is rarely the right fix:

    SHOW VARIABLES LIKE 'innodb_page_size';
    

Additional Information

  • The 65,535-byte limit is a MySQL server-level constraint that applies regardless of storage engine for fixed-length column definitions. InnoDB's effective in-page limit is lower (~8,126 bytes with a 16 KB page and COMPACT/REDUNDANT format).
  • DYNAMIC and COMPRESSED row formats require innodb_file_per_table=ON (the default since MySQL 5.6) and the Barracuda file format (the default in MySQL 8.0).
  • In MySQL 8.0, innodb_file_format was removed; DYNAMIC is the default row format and is always available.
  • BLOB and TEXT columns are exempt from the 65,535 row size check because their content is stored separately, but at least 9–12 bytes of pointer data per column does count against the in-page budget.
  • Related errors: ERROR 1074 (42000): Column length too big for column (single column exceeds its type's limit) and ERROR 1071 (42000): Specified key was too long (index key length limit).

Frequently Asked Questions

Why does this error appear after switching my character set to utf8mb4? Each character in utf8mb4 can occupy up to 4 bytes. MySQL calculates maximum possible row size based on declared column lengths, not actual data. A VARCHAR(255) CHARACTER SET utf8mb4 column counts as up to 1,020 bytes toward the row size limit, versus 255 bytes for latin1. Switching the character set on a wide table can multiply the calculated row size by up to four.

Does switching to ROW_FORMAT=DYNAMIC affect query performance? Generally no — and in many cases it improves performance. Off-page storage for large variable-length columns means the clustered index pages hold more rows, improving cache efficiency for queries that only read shorter columns. The overhead of following off-page pointers only matters when accessing the full content of large columns.

My table definition has TEXT columns — why is this error still occurring? TEXT and BLOB columns themselves are exempt, but if your table also has many VARCHAR, CHAR, or fixed-length columns, those alone may exceed the limit. Run the information_schema.columns query above (filtering to non-TEXT/BLOB types) to identify which fixed columns are contributing to the oversized row.

Can I set ROW_FORMAT=DYNAMIC as a default for all new tables? Yes. Set innodb_default_row_format=DYNAMIC in my.cnf (or my.ini) and restart MySQL. This makes DYNAMIC the default for any new InnoDB table that does not explicitly specify a row format. In MySQL 8.0 this is already the default.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.