Bug #119300 Debug assertion failure: field.field_no < dict_index_get_n_fields(index)
Submitted: 4 Nov 10:46 Modified: 4 Nov 10:56
Reporter: Satya Bodapati (OCA) Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:8.0.44 OS:Any
Assigned to: CPU Architecture:Any

[4 Nov 10:46] Satya Bodapati
Description:
This is a regression from fix:  Fixed an issue related to virtual indexes. (Bug #37602657)

https://github.com/mysql/mysql-server/commit/f97c71a08fb

If table is ROW_FORMAT=REDUNDANT, validate_for_index() introduced in the above commit causes assertion failure during recovery.

 Assertion failure: row0upd.h:645:field.field_no < dict_index_get_n_fields(index) thread 140263467071040
2025-10-31T14:35:00.270018Z 1 [Note] [MY-012533] [InnoDB] 100%
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
2025-10-31T14:35:00Z UTC - mysqld got signal 6 ;
Most likely, you have hit a bug, but this error can also be caused by malfunctioning hardware.
BuildID[sha1]=2327b773761ae2bcdb88a8b39d5a146e92725976
Server Version: 8.0.44-35-debug Source distribution

Thread pointer: 0x0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 0 thread_stack 0x100000
 #0 0x562c3a529110 _Z18print_fatal_signali at sql/signal_handler.cc:160
 #1 0x562c3a529402 _Z15my_server_abortv at sql/signal_handler.cc:295
 #2 0x562c3b86cfcd _Z8my_abortv at mysys/my_init.cc:270
 #3 0x562c3bce4bc9 _Z23ut_dbg_assertion_failedPKcS0_m at storage/innobase/ut/ut0dbg.cc:100
 #4 0x562c3b92b251 _ZNK5upd_t18validate_for_indexEPK12dict_index_t at storage/innobase/include/row0upd.h:645
 #5 0x562c3bc0d763 _Z20row_upd_rec_in_placePhPK12dict_index_tPKmPK5upd_tP14page_zip_des_t at storage/innobase/row/row0upd.cc:488
 #6 0x562c3bd6f971 _Z29btr_cur_parse_update_in_placePhS_S_P14page_zip_des_tP12dict_index_t at storage/innobase/btr/btr0cur.cc:3307
 #7 0x562c3baaba6d recv_parse_or_apply_log_rec_body at storage/innobase/log/log0recv.cc:1941
 #8 0x562c3baae27f _Z22recv_recover_page_funcbP11buf_block_t at storage/innobase/log/log0recv.cc:2673
 #9 0x562c3bd92595 recv_recover_page at storage/innobase/include/log0recv.h:189
 #10 0x562c3bda6794 _Z20buf_page_io_completeP10buf_page_tb at storage/innobase/buf/buf0buf.cc:5910
 #11 0x562c3bf52a40 _Z12fil_aio_waitm at storage/innobase/fil/fil0fil.cc:8028
 #12 0x562c3baf4363 io_handler_thread at storage/innobase/os/os0file.cc:6450
 #13 0x562c3bb02c4b _ZSt13__invoke_implIvPFvmEJmEET_St14__invoke_otherOT0_DpOT1_ at /usr/include/c++/11/bits/invoke.h:61
 #14 0x562c3bb02c0c _ZSt8__invokeIPFvmEJmEENSt15__invoke_resultIT_JDpT0_EE4typeEOS3_DpOS4_ at /usr/include/c++/11/bits/invoke.h:96
 #15 0x562c3bb02bca _ZSt6invokeIPFvmEJmEENSt13invoke_resultIT_JDpT0_EE4typeEOS3_DpOS4_ at /usr/include/c++/11/functional:97
 #16 0x562c3bb02b55 _ZN15Detached_threadclIPFvmEJmEEEvOT_DpOT0_ at storage/innobase/include/os0thread-create.h:191
 #17 0x562c3bb02a46 _ZSt13__invoke_implIv15Detached_threadJPFvmEmEET_St14__invoke_otherOT0_DpOT1_ at /usr/include/c++/11/bits/invoke.h:61
 #18 0x562c3bb0299b _ZSt8__invokeI15Detached_threadJPFvmEmEENSt15__invoke_resultIT_JDpT0_EE4typeEOS4_DpOS5_ at /usr/include/c++/11/bits/invoke.h:96
 #19 0x562c3bb028a4 _ZNSt6thread8_InvokerISt5tupleIJ15Detached_threadPFvmEmEEE9_M_invokeIJLm0ELm1ELm2EEEEvSt12_Index_tupleIJXspT_EEE at /usr/include/c++/11/bits/std_thread.h:259
 #20 0x562c3bb02785 _ZNSt6thread8_InvokerISt5tupleIJ15Detached_threadPFvmEmEEEclEv at /usr/include/c++/11/bits/std_thread.h:266
 #21 0x562c3bb02451 _ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJ15Detached_threadPFvmEmEEEEE6_M_runEv at /usr/include/c++/11/bits/std_thread.h:211
 #22 0x7f91b0adc252 <unknown>
 #23 0x7f91b0694ac2 start_thread at ./nptl/pthread_create.c:442
 #24 0x7f91b07268bf <unknown> at sysdeps/unix/sysv/linux/x86_64/clone3.S:81
 #25 0xffffffffffffffff <unknown>
Please help us make Percona Server better by report

How to repeat:
(on debug build)

create table t1(a INT PRIMARY KEY, b INT, KEY k1(b)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
insert into t1 values (1,1), (2,2), (3,3), (4,4);
SET GLOBAL innodb_log_checkpoint_now=ON;
set global innodb_checkpoint_disabled=true;
set global innodb_page_cleaner_disabled_debug=ON;
update t1 set b=5 where a=1;
--source include/kill_and_restart_mysqld.inc

SELECT * FROM t1;

DROP TABLE t1;

Suggested fix:
a band-aid fix:
For redundant format, since we dont log index field number properly for recovery, we disable this check only on recvoery + redundant

git diff
diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h
index 135ce17d8bf..b8c4468a739 100644
--- a/storage/innobase/include/row0upd.h
+++ b/storage/innobase/include/row0upd.h
@@ -638,6 +638,8 @@ struct upd_t {
 
   void validate_for_index(const dict_index_t *index) const {
     validate();
+    if (recv_recovery_on && !dict_table_is_comp(index->table)) return;
+
     for (ulint i = 0; i < n_fields; ++i) {
       const upd_field_t &field = fields[i];
       ut_a(index->is_clustered() || !field.is_virtual());

Another possibility is do properly logging index fields for redundant format fields. This will ofcourse change the redo logging for such REDUNDANT table. We have to be careful about upgrade & downgrade scenarios? (imagine the fix between 8.4.5 & 8.4.6)
[4 Nov 10:49] Satya Bodapati
The commit is introduced in 8.0.44
[4 Nov 10:56] Satya Bodapati
updated version field