Description:
In-place upgrade to MySQL 8.0.42+ or 8.4.5+ fails with MY-013135 ("Incorrect information in file") when both of these conditions exist on the instance:
1. A stored procedure whose body contains `CREATE TEMPORARY TABLE ... ENGINE=Memory`
2. A table with CHECK constraints, generated columns, or partition expressions that use SQL functions (e.g., `regexp_like()`)
Either condition alone does not cause the failure. Both must be present.
The root cause is in `sql/dd/impl/upgrade/server.cc`. During `do_server_upgrade_checks()`, the `check_routines` phase compiles stored procedures. When it encounters `ENGINE=Memory`, `resolve_engine()` fails because the MEMORY storage engine is not loaded during bootstrap. This sets error 1286 (`ER_UNKNOWN_STORAGE_ENGINE`) in the THD diagnostics area. The function `invalid_routine()` returns early without clearing the error:
```c
// sql/dd/impl/upgrade/server.cc — invalid_routine()
if (error) return (thd->get_stmt_da()->mysql_errno() == ER_PARSE_ERROR);
thd->clear_error(); // ONLY reached when error == false
```
The stale THD error then propagates to `check_table_funs()` (added in MySQL 8.4.5, backported to 8.0.42+), which calls `open_table()` → `open_table_from_share()` → `unpack_value_generator()` → `fix_fields()`. Expression evaluation sees the stale `is_error()` and fails, producing MY-013135.
The `invalid_routine()` function is byte-for-byte identical in 8.0.40, 8.0.44, 8.4.4, and 8.4.5. The bug was latent until `check_table_funs` was added to the `process_schema` pipeline.
Related: Bug #120326 (identical mechanism with partitioned tables instead of CHECK constraints)
How to repeat:
### 1. Deploy MySQL 8.0.40 (or any version below 8.0.42)
```bash
mysqld --initialize-insecure --datadir=/tmp/repro_data --basedir=/path/to/mysql-8.0.40
mysqld --defaults-file=/dev/null --datadir=/tmp/repro_data --port=3307 \
--socket=/tmp/repro.sock --log-error=/tmp/repro.err --log_error_verbosity=3 &
```
### 2. Create stored procedure with ENGINE=Memory (condition 1)
```sql
CREATE DATABASE testrepro;
USE testrepro;
DELIMITER //
CREATE PROCEDURE my_proc()
BEGIN
CREATE TEMPORARY TABLE IF NOT EXISTS temp_memory (
id BIGINT PRIMARY KEY
) ENGINE=Memory;
DROP TEMPORARY TABLE IF EXISTS temp_memory;
END //
DELIMITER ;
```
### 3. Create table with CHECK constraints using regexp_like() (condition 2)
```sql
CREATE TABLE job_config (
id smallint unsigned NOT NULL AUTO_INCREMENT,
source_name varchar(128) NOT NULL,
target_name varchar(128) NOT NULL,
fallback_name varchar(128) DEFAULT NULL,
job_type enum('standard','tiered','custom') NOT NULL DEFAULT 'standard',
filter_col varchar(128) NOT NULL DEFAULT 'created_at',
retain_months smallint unsigned NOT NULL DEFAULT '36',
expire_months smallint unsigned NOT NULL DEFAULT '84',
stage_months smallint unsigned DEFAULT NULL,
active tinyint(1) NOT NULL DEFAULT '1',
priority smallint unsigned NOT NULL DEFAULT '100',
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uq_source (source_name),
KEY idx_type_active (job_type, active, priority),
CONSTRAINT chk_retain_min CHECK ((retain_months >= 6)),
CONSTRAINT chk_target_name CHECK (regexp_like(target_name,_utf8mb4'^[a-zA-Z_][a-zA-Z0-9_]*$')),
CONSTRAINT chk_fallback_name CHECK (((fallback_name is null) or regexp_like(fallback_name,_utf8mb4'^[a-zA-Z_][a-zA-Z0-9_]*$'))),
CONSTRAINT chk_source_name CHECK (regexp_like(source_name,_utf8mb4'^[a-zA-Z_][a-zA-Z0-9_]*$')),
CONSTRAINT chk_expire_gt_retain CHECK ((expire_months > retain_months)),
CONSTRAINT chk_expire_min CHECK ((expire_months >= 6)),
CONSTRAINT chk_filter_col CHECK (regexp_like(filter_col,_utf8mb4'^[a-zA-Z_][a-zA-Z0-9_]*$')),
CONSTRAINT chk_tiered CHECK (((job_type <> _utf8mb4'tiered') or ((fallback_name is not null) and (stage_months is not null))))
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO job_config (source_name, target_name) VALUES ('events', 'events_history');
```
### 4. Stop 8.0.40 and start 8.4.5 (or 8.0.44)
```bash
mysqladmin -S /tmp/repro.sock shutdown
/path/to/mysql-8.4.5/bin/mysqld --defaults-file=/dev/null \
--datadir=/tmp/repro_data --port=3307 --socket=/tmp/repro.sock \
--log-error=/tmp/repro_upgrade.err --log_error_verbosity=3 --upgrade=AUTO
```
### 5. Observe failure
```
[ERROR] [MY-013135] [Server] Incorrect information in file: './testrepro/job_config.frm'
[Warning] [MY-014078] [Server] Can not open table `testrepro`.`job_config`; functions in constraints, partitions, or virtual columns may have failed.
[ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
[ERROR] [MY-010119] [Server] Aborting
```
### 6. Verify: drop the stored procedure, retry — SUCCEEDS
On a fresh datadir with the same table but no stored procedure referencing ENGINE=Memory, upgrade to 8.4.5 completes without error.
### 7. Verify: drop the CHECK constraints, retry — SUCCEEDS
On a fresh datadir with the stored procedure but only simple CHECK constraints (no `regexp_like()` or other function calls), upgrade to 8.4.5 completes without error.
---
## Test Matrix (confirmed)
| Source | Target | check_table_funs? | Result |
|--------|--------|-------------------|--------|
| 8.0.40 | 8.0.44 | YES | FAILED |
| 8.0.40 | 8.4.4 | NO | SUCCEEDED |
| 8.0.40 | 8.4.5 | YES | FAILED |
| 8.0.40 | 8.4.6 | YES | FAILED |
| 8.0.40 | 8.4.7 | YES | FAILED |
| 8.0.44 (fresh) | 8.4.4 | NO | SUCCEEDED |
| 8.0.44 (fresh) | 8.4.5 | YES | FAILED |
---
Suggested fix:
Clear THD before calling `check_table_funs`:
```c
// sql/dd/impl/upgrade/server.cc — do_server_upgrade_checks()
auto process_schema = [&](std::unique_ptr<Schema> &schema) {
return check_tables(...) || check_events(...) || check_routines(...) || check_views(...) ||
(thd->clear_error(), false) ||
check_table_funs(...);
};
```
Description: In-place upgrade to MySQL 8.0.42+ or 8.4.5+ fails with MY-013135 ("Incorrect information in file") when both of these conditions exist on the instance: 1. A stored procedure whose body contains `CREATE TEMPORARY TABLE ... ENGINE=Memory` 2. A table with CHECK constraints, generated columns, or partition expressions that use SQL functions (e.g., `regexp_like()`) Either condition alone does not cause the failure. Both must be present. The root cause is in `sql/dd/impl/upgrade/server.cc`. During `do_server_upgrade_checks()`, the `check_routines` phase compiles stored procedures. When it encounters `ENGINE=Memory`, `resolve_engine()` fails because the MEMORY storage engine is not loaded during bootstrap. This sets error 1286 (`ER_UNKNOWN_STORAGE_ENGINE`) in the THD diagnostics area. The function `invalid_routine()` returns early without clearing the error: ```c // sql/dd/impl/upgrade/server.cc — invalid_routine() if (error) return (thd->get_stmt_da()->mysql_errno() == ER_PARSE_ERROR); thd->clear_error(); // ONLY reached when error == false ``` The stale THD error then propagates to `check_table_funs()` (added in MySQL 8.4.5, backported to 8.0.42+), which calls `open_table()` → `open_table_from_share()` → `unpack_value_generator()` → `fix_fields()`. Expression evaluation sees the stale `is_error()` and fails, producing MY-013135. The `invalid_routine()` function is byte-for-byte identical in 8.0.40, 8.0.44, 8.4.4, and 8.4.5. The bug was latent until `check_table_funs` was added to the `process_schema` pipeline. Related: Bug #120326 (identical mechanism with partitioned tables instead of CHECK constraints) How to repeat: ### 1. Deploy MySQL 8.0.40 (or any version below 8.0.42) ```bash mysqld --initialize-insecure --datadir=/tmp/repro_data --basedir=/path/to/mysql-8.0.40 mysqld --defaults-file=/dev/null --datadir=/tmp/repro_data --port=3307 \ --socket=/tmp/repro.sock --log-error=/tmp/repro.err --log_error_verbosity=3 & ``` ### 2. Create stored procedure with ENGINE=Memory (condition 1) ```sql CREATE DATABASE testrepro; USE testrepro; DELIMITER // CREATE PROCEDURE my_proc() BEGIN CREATE TEMPORARY TABLE IF NOT EXISTS temp_memory ( id BIGINT PRIMARY KEY ) ENGINE=Memory; DROP TEMPORARY TABLE IF EXISTS temp_memory; END // DELIMITER ; ``` ### 3. Create table with CHECK constraints using regexp_like() (condition 2) ```sql CREATE TABLE job_config ( id smallint unsigned NOT NULL AUTO_INCREMENT, source_name varchar(128) NOT NULL, target_name varchar(128) NOT NULL, fallback_name varchar(128) DEFAULT NULL, job_type enum('standard','tiered','custom') NOT NULL DEFAULT 'standard', filter_col varchar(128) NOT NULL DEFAULT 'created_at', retain_months smallint unsigned NOT NULL DEFAULT '36', expire_months smallint unsigned NOT NULL DEFAULT '84', stage_months smallint unsigned DEFAULT NULL, active tinyint(1) NOT NULL DEFAULT '1', priority smallint unsigned NOT NULL DEFAULT '100', created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_source (source_name), KEY idx_type_active (job_type, active, priority), CONSTRAINT chk_retain_min CHECK ((retain_months >= 6)), CONSTRAINT chk_target_name CHECK (regexp_like(target_name,_utf8mb4'^[a-zA-Z_][a-zA-Z0-9_]*$')), CONSTRAINT chk_fallback_name CHECK (((fallback_name is null) or regexp_like(fallback_name,_utf8mb4'^[a-zA-Z_][a-zA-Z0-9_]*$'))), CONSTRAINT chk_source_name CHECK (regexp_like(source_name,_utf8mb4'^[a-zA-Z_][a-zA-Z0-9_]*$')), CONSTRAINT chk_expire_gt_retain CHECK ((expire_months > retain_months)), CONSTRAINT chk_expire_min CHECK ((expire_months >= 6)), CONSTRAINT chk_filter_col CHECK (regexp_like(filter_col,_utf8mb4'^[a-zA-Z_][a-zA-Z0-9_]*$')), CONSTRAINT chk_tiered CHECK (((job_type <> _utf8mb4'tiered') or ((fallback_name is not null) and (stage_months is not null)))) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO job_config (source_name, target_name) VALUES ('events', 'events_history'); ``` ### 4. Stop 8.0.40 and start 8.4.5 (or 8.0.44) ```bash mysqladmin -S /tmp/repro.sock shutdown /path/to/mysql-8.4.5/bin/mysqld --defaults-file=/dev/null \ --datadir=/tmp/repro_data --port=3307 --socket=/tmp/repro.sock \ --log-error=/tmp/repro_upgrade.err --log_error_verbosity=3 --upgrade=AUTO ``` ### 5. Observe failure ``` [ERROR] [MY-013135] [Server] Incorrect information in file: './testrepro/job_config.frm' [Warning] [MY-014078] [Server] Can not open table `testrepro`.`job_config`; functions in constraints, partitions, or virtual columns may have failed. [ERROR] [MY-010020] [Server] Data Dictionary initialization failed. [ERROR] [MY-010119] [Server] Aborting ``` ### 6. Verify: drop the stored procedure, retry — SUCCEEDS On a fresh datadir with the same table but no stored procedure referencing ENGINE=Memory, upgrade to 8.4.5 completes without error. ### 7. Verify: drop the CHECK constraints, retry — SUCCEEDS On a fresh datadir with the stored procedure but only simple CHECK constraints (no `regexp_like()` or other function calls), upgrade to 8.4.5 completes without error. --- ## Test Matrix (confirmed) | Source | Target | check_table_funs? | Result | |--------|--------|-------------------|--------| | 8.0.40 | 8.0.44 | YES | FAILED | | 8.0.40 | 8.4.4 | NO | SUCCEEDED | | 8.0.40 | 8.4.5 | YES | FAILED | | 8.0.40 | 8.4.6 | YES | FAILED | | 8.0.40 | 8.4.7 | YES | FAILED | | 8.0.44 (fresh) | 8.4.4 | NO | SUCCEEDED | | 8.0.44 (fresh) | 8.4.5 | YES | FAILED | --- Suggested fix: Clear THD before calling `check_table_funs`: ```c // sql/dd/impl/upgrade/server.cc — do_server_upgrade_checks() auto process_schema = [&](std::unique_ptr<Schema> &schema) { return check_tables(...) || check_events(...) || check_routines(...) || check_views(...) || (thd->clear_error(), false) || check_table_funs(...); }; ```