Repository: duckdb/duckdb (language: python)

Issue:
Segmentation fault
### What happens?

Sometimes a segmentation fault when DuckDB is backed by a file, in-memory it does not issue a seg fault.

Out of 277 datasets, only 5 have this issue. With provided dataset, can always be reproduced.

```
(gdb) bt
#0  0x0000555555775ed6 in std::__shared_ptr<duckdb::DataTableInfo, (__gnu_cxx::_Lock_policy)2>::get (this=0x29c) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:1667
#1  0x00005555557688de in duckdb::shared_ptr<duckdb::DataTableInfo, true>::operator* (this=0x29c) at /home/skinkie/Sources/duckdb/src/include/duckdb/common/shared_ptr_ipp.hpp:196
#2  0x000055555621bb98 in duckdb::RowGroupCollection::GetTableInfo (this=0x28c) at /home/skinkie/Sources/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp:129
#3  0x00005555561e5cc6 in duckdb::RowGroup::GetTableInfo (this=0x55555a7159e0) at /home/skinkie/Sources/duckdb/src/storage/table/row_group.cpp:135
#4  0x00005555561e6c1a in duckdb::RowGroup::AddColumn (this=0x55555a7159e0, new_collection=..., new_column=..., executor=..., result=...) at /home/skinkie/Sources/duckdb/src/storage/table/row_group.cpp:305
#5  0x00005555561f019a in duckdb::RowGroupCollection::AddColumn (this=0x55555a1ee9c0, context=..., new_column=..., default_executor=...) at /home/skinkie/Sources/duckdb/src/storage/table/row_group_collection.cpp:1066
#6  0x0000555556279e05 in duckdb::DataTable::DataTable (this=0x55555a80eaf0, context=..., parent=..., new_column=..., default_value=...) at /home/skinkie/Sources/duckdb/src/storage/data_table.cpp:80
#7  0x00005555557a16e8 in std::_Construct<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (__p=0x55555a80eaf0)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/stl_construct.h:119
#8  0x000055555579c4e8 in std::allocator_traits<std::allocator<void> >::construct<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (__p=0x55555a80eaf0)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/alloc_traits.h:657
#9  std::_Sp_counted_ptr_inplace<duckdb::DataTable, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x55555a80eae0, __a=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:607
#10 0x00005555557974e8 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<duckdb::DataTable, std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x7fffffffa588, __p=@0x7fffffffa580: 0x0, __a=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:969
#11 0x00005555557916e2 in std::__shared_ptr<duckdb::DataTable, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x7fffffffa580, __tag=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:1713
#12 0x0000555555788805 in std::shared_ptr<duckdb::DataTable>::shared_ptr<std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (this=0x7fffffffa580, __tag=...)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr.h:463
#13 0x000055555577cb90 in std::make_shared<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> () at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr.h:1008
#14 0x000055555576f1f0 in duckdb::make_shared_ptr<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> () at /home/skinkie/Sources/duckdb/src/include/duckdb/common/helper.hpp:73
#15 0x0000555555753e98 in duckdb::DuckTableEntry::AddColumn (this=0x55555a196530, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:391
#16 0x000055555575271e in duckdb::DuckTableEntry::AlterEntry (this=0x55555a196530, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:231
#17 0x00005555557522bc in duckdb::DuckTableEntry::AlterEntry (this=0x55555a196530, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:184
#18 0x00005555557b6bd8 in duckdb::CatalogSet::AlterEntry (this=0x55555a16be20, transaction=..., name="kv6_import", alter_info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_set.cpp:328
#19 0x000055555574fcf9 in duckdb::DuckSchemaEntry::Alter (this=0x55555a16bd40, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp:291
#20 0x00005555557b156a in duckdb::Catalog::Alter (this=0x55555a1704e0, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog.cpp:904
#21 0x00005555557b176b in duckdb::Catalog::Alter (this=0x55555a1704e0, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog.cpp:912
#22 0x00005555570b1ff5 in duckdb::PhysicalAlter::GetData (this=0x7fffdc5f55a0, context=..., chunk=..., input=...) at /home/skinkie/Sources/duckdb/src/execution/operator/schema/physical_alter.cpp:13
#23 0x0000555555ff23af in duckdb::PipelineExecutor::GetData (this=0x55555a31e250, chunk=..., input=...) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:478
#24 0x0000555555ff24a0 in duckdb::PipelineExecutor::FetchFromSource (this=0x55555a31e250, result=...) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:504
#25 0x0000555555ff1268 in duckdb::PipelineExecutor::Execute (this=0x55555a31e250, max_chunks=50) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:204
#26 0x0000555555fed597 in duckdb::PipelineTask::ExecuteTask (this=0x7fffdc15fff0, mode=duckdb::TaskExecutionMode::PROCESS_PARTIAL) at /home/skinkie/Sources/duckdb/src/parallel/pipeline.cpp:40
#27 0x0000555555fe7c38 in duckdb::ExecutorTask::Execute (this=0x7fffdc15fff0, mode=duckdb::TaskExecutionMode::PROCESS_PARTIAL) at /home/skinkie/Sources/duckdb/src/parallel/executor_task.cpp:44
#28 0x0000555555feb739 in duckdb::Executor::ExecuteTask (this=0x55555a173350, dry_run=false) at /home/skinkie/Sources/duckdb/src/parallel/executor.cpp:580
#29 0x0000555555eab6d5 in duckdb::ClientContext::ExecuteTaskInternal (this=0x55555a16e960, lock=..., result=..., dry_run=false) at /home/skinkie/Sources/duckdb/src/main/client_context.cpp:557
#30 0x0000555555ec66bd in duckdb::PendingQueryResult::ExecuteTaskInternal (this=0x55555a46b6d0, lock=...) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:68
#31 0x0000555555ec6751 in duckdb::PendingQueryResult::ExecuteInternal (this=0x55555a46b6d0, lock=...) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:75
#32 0x0000555555ec6905 in duckdb::PendingQueryResult::Execute (this=0x55555a46b6d0) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:95
#33 0x0000555555ec72be in duckdb::PreparedStatement::Execute (this=0x55555a4dd5b0, values=..., allow_stream_result=false) at /home/skinkie/Sources/duckdb/src/main/prepared_statement.cpp:85
#34 0x00005555556b91da in duckdb_shell_sqlite3_print_duckbox (pStmt=0x7fffcc091870, max_rows=40, max_width=0, null_value=0x7fffffffc03c "", columnar=0)
    at /home/skinkie/Sources/duckdb/tools/sqlite3_api_wrapper/sqlite3_api_wrapper.cpp:249
#35 0x000055555568be00 in exec_prepared_stmt (pArg=0x7fffffffbf20, pStmt=0x7fffcc091870) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:12752
#36 0x000055555568cc4c in shell_exec (pArg=0x7fffffffbf20, zSql=0x55555a1ef160 "alter table kv6_import add column trip_id varchar(16);", pzErrMsg=0x7fffffffbdb0) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:13087
#37 0x0000555555699c79 in runOneSqlLine (p=0x7fffffffbf20, zSql=0x55555a1ef160 "alter table kv6_import add column trip_id varchar(16);", in=0x55555a31e000, startline=31) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19273
#38 0x000055555569a16f in process_input (p=0x7fffffffbf20) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19384
#39 0x000055555569a49a in process_sqliterc (p=0x7fffffffbf20, sqliterc_override=0x7fffffffd720 "/tmp/script.sql") at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19505
#40 0x000055555569b174 in main (argc=4, argv=0x7fffffffd258) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19951
```

### To Reproduce

```sql
DROP TABLE IF EXISTS kv6_import;
DROP TABLE IF EXISTS tt_import;

CREATE TABLE "kv6_import" (
        "receive"                   TIMESTAMP     NOT NULL,
        "message"                   TIMESTAMP     NOT NULL,
        "vehicle"                   TIMESTAMP     NOT NULL,
        "messagetype"               VARCHAR(10)   NOT NULL,
        "operatingday"              DATE          NOT NULL,
        "dataownercode"             VARCHAR(10)   NOT NULL,
        "lineplanningnumber"        VARCHAR(10),
        "journeynumber"             UINTEGER       NOT NULL,
        "reinforcementnumber"       UTINYINT       NOT NULL,
        "userstopcode"              VARCHAR(10),
        "passagesequencenumber"     TINYINT,
        "distancesincelastuserstop" INTEGER,
        "punctuality"               INTEGER,
        "rd_x"                      VARCHAR(11),
        "rd_y"                      VARCHAR(11),
        "blockcode"                 INTEGER,
        "vehiclenumber"             SMALLINT,
        "wheelchairaccessible"      VARCHAR(5),
        "source"                    VARCHAR(10)   NOT NULL,
        "numberofcoaches"           UTINYINT
);

copy kv6_import from '/tmp/kv6-20240917.log' (DELIMITER ';');

delete from kv6_import where messagetype not in ('ARRIVAL', 'DEPARTURE');

alter table kv6_import add column trip_id varchar(16);

update kv6_import set trip_id = dataownercode || ':' || lineplanningnumber || ':' || journeynumber;

CREATE TABLE "tt_import" (
        "operatingday"          DATE          NOT NULL,
        "trip_id"               VARCHAR(16)   NOT NULL,
        "pointorder"            UTINYINT      NOT NULL,
        "passagesequencenumber" UTINYINT      NOT NULL,
        "userstopcode"          VARCHAR(10)   NOT NULL,
        "targetarrivaltime"     VARCHAR(8)    NOT NULL,
        "targetdeparturetime"   VARCHAR(8)    NOT NULL,
        "recordedarrivaltime"   VARCHAR(8),
        "recordeddeparturetime" VARCHAR(8)
);

copy tt_import from '/tmp/transittimes.csv' (DELIMITER ',');

delete from tt_import where trip_id like 'DOEKSEN:%' or trip_id like 'WSF:%' or trip_id like 'IFF%' or trip_id like 'WPD%' or trip_id like 'TESO%';

alter table tt_import drop column recordedarrivaltime;
alter table tt_import drop column recordeddeparturetime;

update kv6_import set trip_id = w.trip_id from (select tt_import.trip_id as trip_id, z.trip_id as kv6_trip_id, vehiclenumber from tt_import join (select trip_id, userstopcode, vehiclenumber from kv6_import join (select trip_id, min(receive) as receive from kv6_import where trip_id in (select trip_id from kv6_import where trip_id like 'ARR:%' and length(trip_id) = 13  except select trip_id from tt_import) group by trip_id) as y using (trip_id, receive)) as z using (userstopcode) where pointorder = 1 and tt_import.trip_id like z.trip_id[0:8] || '_' || z.trip_id[-5:]) as w where kv6_import.trip_id = kv6_trip_id and kv6_import.vehiclenumber = w.vehiclenumber;

copy (select tt_import.operatingday, tt_import.trip_id, x.reinforcementnumber, x.vehiclenumber, tt_import.userstopcode, tt_import.passagesequencenumber, tt_import.pointorder, tt_import.targetarrivaltime, tt_import.targetdeparturetime, x.arrival as recordedarrivaltime, x.departure as recordeddeparturetime from (select trip_id, reinforcementnumber, vehiclenumber, userstopcode, passagesequencenumber, max(a.receive) as arrival, max(b.receive) as departure from kv6_import as a full outer join kv6_import as b using (trip_id, reinforcementnumber, userstopcode, passagesequencenumber, vehiclenumber) where a.messagetype = 'ARRIVAL' and b.messagetype = 'DEPARTURE' group by trip_id, reinforcementnumber, userstopcode, passagesequencenumber, vehiclenumber) as x right join tt_import using (trip_id, userstopcode, passagesequencenumber) order by trip_id, reinforcementnumber, pointorder) to '/home/skinkie/arriva/volledig-20240917.csv.gz' header;
```

Data:
https://download.stefan.konink.de/duckdb/kv6-20240917.log.gz
https://download.stefan.konink.de/duckdb/transittimes.csv.gz


### OS:

Linux

### DuckDB Version:

main

### DuckDB Client:

cli

### Hardware:

amd64

### Full Name:

Stefan de Konink

### Affiliation:

Stichting OpenGeo

### What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.

I have tested with a source build

### Did you include all relevant data sets for reproducing the issue?

No - Other reason (please specify in the issue body)

### Did you include all code required to reproduce the issue?

- [X] Yes, I have

### Did you include all relevant configuration (e.g., CPU architecture, Python version, Linux distribution) to reproduce the issue?

- [X] Yes, I have
Segmentation fault
### What happens?

Sometimes a segmentation fault when DuckDB is backed by a file, in-memory it does not issue a seg fault.

Out of 277 datasets, only 5 have this issue. With provided dataset, can always be reproduced.

```
(gdb) bt
#0  0x0000555555775ed6 in std::__shared_ptr<duckdb::DataTableInfo, (__gnu_cxx::_Lock_policy)2>::get (this=0x29c) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:1667
#1  0x00005555557688de in duckdb::shared_ptr<duckdb::DataTableInfo, true>::operator* (this=0x29c) at /home/skinkie/Sources/duckdb/src/include/duckdb/common/shared_ptr_ipp.hpp:196
#2  0x000055555621bb98 in duckdb::RowGroupCollection::GetTableInfo (this=0x28c) at /home/skinkie/Sources/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp:129
#3  0x00005555561e5cc6 in duckdb::RowGroup::GetTableInfo (this=0x55555a7159e0) at /home/skinkie/Sources/duckdb/src/storage/table/row_group.cpp:135
#4  0x00005555561e6c1a in duckdb::RowGroup::AddColumn (this=0x55555a7159e0, new_collection=..., new_column=..., executor=..., result=...) at /home/skinkie/Sources/duckdb/src/storage/table/row_group.cpp:305
#5  0x00005555561f019a in duckdb::RowGroupCollection::AddColumn (this=0x55555a1ee9c0, context=..., new_column=..., default_executor=...) at /home/skinkie/Sources/duckdb/src/storage/table/row_group_collection.cpp:1066
#6  0x0000555556279e05 in duckdb::DataTable::DataTable (this=0x55555a80eaf0, context=..., parent=..., new_column=..., default_value=...) at /home/skinkie/Sources/duckdb/src/storage/data_table.cpp:80
#7  0x00005555557a16e8 in std::_Construct<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (__p=0x55555a80eaf0)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/stl_construct.h:119
#8  0x000055555579c4e8 in std::allocator_traits<std::allocator<void> >::construct<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (__p=0x55555a80eaf0)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/alloc_traits.h:657
#9  std::_Sp_counted_ptr_inplace<duckdb::DataTable, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x55555a80eae0, __a=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:607
#10 0x00005555557974e8 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<duckdb::DataTable, std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x7fffffffa588, __p=@0x7fffffffa580: 0x0, __a=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:969
#11 0x00005555557916e2 in std::__shared_ptr<duckdb::DataTable, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x7fffffffa580, __tag=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:1713
#12 0x0000555555788805 in std::shared_ptr<duckdb::DataTable>::shared_ptr<std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (this=0x7fffffffa580, __tag=...)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr.h:463
#13 0x000055555577cb90 in std::make_shared<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> () at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr.h:1008
#14 0x000055555576f1f0 in duckdb::make_shared_ptr<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> () at /home/skinkie/Sources/duckdb/src/include/duckdb/common/helper.hpp:73
#15 0x0000555555753e98 in duckdb::DuckTableEntry::AddColumn (this=0x55555a196530, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:391
#16 0x000055555575271e in duckdb::DuckTableEntry::AlterEntry (this=0x55555a196530, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:231
#17 0x00005555557522bc in duckdb::DuckTableEntry::AlterEntry (this=0x55555a196530, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:184
#18 0x00005555557b6bd8 in duckdb::CatalogSet::AlterEntry (this=0x55555a16be20, transaction=..., name="kv6_import", alter_info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_set.cpp:328
#19 0x000055555574fcf9 in duckdb::DuckSchemaEntry::Alter (this=0x55555a16bd40, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp:291
#20 0x00005555557b156a in duckdb::Catalog::Alter (this=0x55555a1704e0, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog.cpp:904
#21 0x00005555557b176b in duckdb::Catalog::Alter (this=0x55555a1704e0, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog.cpp:912
#22 0x00005555570b1ff5 in duckdb::PhysicalAlter::GetData (this=0x7fffdc5f55a0, context=..., chunk=..., input=...) at /home/skinkie/Sources/duckdb/src/execution/operator/schema/physical_alter.cpp:13
#23 0x0000555555ff23af in duckdb::PipelineExecutor::GetData (this=0x55555a31e250, chunk=..., input=...) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:478
#24 0x0000555555ff24a0 in duckdb::PipelineExecutor::FetchFromSource (this=0x55555a31e250, result=...) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:504
#25 0x0000555555ff1268 in duckdb::PipelineExecutor::Execute (this=0x55555a31e250, max_chunks=50) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:204
#26 0x0000555555fed597 in duckdb::PipelineTask::ExecuteTask (this=0x7fffdc15fff0, mode=duckdb::TaskExecutionMode::PROCESS_PARTIAL) at /home/skinkie/Sources/duckdb/src/parallel/pipeline.cpp:40
#27 0x0000555555fe7c38 in duckdb::ExecutorTask::Execute (this=0x7fffdc15fff0, mode=duckdb::TaskExecutionMode::PROCESS_PARTIAL) at /home/skinkie/Sources/duckdb/src/parallel/executor_task.cpp:44
#28 0x0000555555feb739 in duckdb::Executor::ExecuteTask (this=0x55555a173350, dry_run=false) at /home/skinkie/Sources/duckdb/src/parallel/executor.cpp:580
#29 0x0000555555eab6d5 in duckdb::ClientContext::ExecuteTaskInternal (this=0x55555a16e960, lock=..., result=..., dry_run=false) at /home/skinkie/Sources/duckdb/src/main/client_context.cpp:557
#30 0x0000555555ec66bd in duckdb::PendingQueryResult::ExecuteTaskInternal (this=0x55555a46b6d0, lock=...) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:68
#31 0x0000555555ec6751 in duckdb::PendingQueryResult::ExecuteInternal (this=0x55555a46b6d0, lock=...) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:75
#32 0x0000555555ec6905 in duckdb::PendingQueryResult::Execute (this=0x55555a46b6d0) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:95
#33 0x0000555555ec72be in duckdb::PreparedStatement::Execute (this=0x55555a4dd5b0, values=..., allow_stream_result=false) at /home/skinkie/Sources/duckdb/src/main/prepared_statement.cpp:85
#34 0x00005555556b91da in duckdb_shell_sqlite3_print_duckbox (pStmt=0x7fffcc091870, max_rows=40, max_width=0, null_value=0x7fffffffc03c "", columnar=0)
    at /home/skinkie/Sources/duckdb/tools/sqlite3_api_wrapper/sqlite3_api_wrapper.cpp:249
#35 0x000055555568be00 in exec_prepared_stmt (pArg=0x7fffffffbf20, pStmt=0x7fffcc091870) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:12752
#36 0x000055555568cc4c in shell_exec (pArg=0x7fffffffbf20, zSql=0x55555a1ef160 "alter table kv6_import add column trip_id varchar(16);", pzErrMsg=0x7fffffffbdb0) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:13087
#37 0x0000555555699c79 in runOneSqlLine (p=0x7fffffffbf20, zSql=0x55555a1ef160 "alter table kv6_import add column trip_id varchar(16);", in=0x55555a31e000, startline=31) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19273
#38 0x000055555569a16f in process_input (p=0x7fffffffbf20) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19384
#39 0x000055555569a49a in process_sqliterc (p=0x7fffffffbf20, sqliterc_override=0x7fffffffd720 "/tmp/script.sql") at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19505
#40 0x000055555569b174 in main (argc=4, argv=0x7fffffffd258) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19951
```

### To Reproduce

```sql
DROP TABLE IF EXISTS kv6_import;
DROP TABLE IF EXISTS tt_import;

CREATE TABLE "kv6_import" (
        "receive"                   TIMESTAMP     NOT NULL,
        "message"                   TIMESTAMP     NOT NULL,
        "vehicle"                   TIMESTAMP     NOT NULL,
        "messagetype"               VARCHAR(10)   NOT NULL,
        "operatingday"              DATE          NOT NULL,
        "dataownercode"             VARCHAR(10)   NOT NULL,
        "lineplanningnumber"        VARCHAR(10),
        "journeynumber"             UINTEGER       NOT NULL,
        "reinforcementnumber"       UTINYINT       NOT NULL,
        "userstopcode"              VARCHAR(10),
        "passagesequencenumber"     TINYINT,
        "distancesincelastuserstop" INTEGER,
        "punctuality"               INTEGER,
        "rd_x"                      VARCHAR(11),
        "rd_y"                      VARCHAR(11),
        "blockcode"                 INTEGER,
        "vehiclenumber"             SMALLINT,
        "wheelchairaccessible"      VARCHAR(5),
        "source"                    VARCHAR(10)   NOT NULL,
        "numberofcoaches"           UTINYINT
);

copy kv6_import from '/tmp/kv6-20240917.log' (DELIMITER ';');

delete from kv6_import where messagetype not in ('ARRIVAL', 'DEPARTURE');

alter table kv6_import add column trip_id varchar(16);

update kv6_import set trip_id = dataownercode || ':' || lineplanningnumber || ':' || journeynumber;

CREATE TABLE "tt_import" (
        "operatingday"          DATE          NOT NULL,
        "trip_id"               VARCHAR(16)   NOT NULL,
        "pointorder"            UTINYINT      NOT NULL,
        "passagesequencenumber" UTINYINT      NOT NULL,
        "userstopcode"          VARCHAR(10)   NOT NULL,
        "targetarrivaltime"     VARCHAR(8)    NOT NULL,
        "targetdeparturetime"   VARCHAR(8)    NOT NULL,
        "recordedarrivaltime"   VARCHAR(8),
        "recordeddeparturetime" VARCHAR(8)
);

copy tt_import from '/tmp/transittimes.csv' (DELIMITER ',');

delete from tt_import where trip_id like 'DOEKSEN:%' or trip_id like 'WSF:%' or trip_id like 'IFF%' or trip_id like 'WPD%' or trip_id like 'TESO%';

alter table tt_import drop column recordedarrivaltime;
alter table tt_import drop column recordeddeparturetime;

update kv6_import set trip_id = w.trip_id from (select tt_import.trip_id as trip_id, z.trip_id as kv6_trip_id, vehiclenumber from tt_import join (select trip_id, userstopcode, vehiclenumber from kv6_import join (select trip_id, min(receive) as receive from kv6_import where trip_id in (select trip_id from kv6_import where trip_id like 'ARR:%' and length(trip_id) = 13  except select trip_id from tt_import) group by trip_id) as y using (trip_id, receive)) as z using (userstopcode) where pointorder = 1 and tt_import.trip_id like z.trip_id[0:8] || '_' || z.trip_id[-5:]) as w where kv6_import.trip_id = kv6_trip_id and kv6_import.vehiclenumber = w.vehiclenumber;

copy (select tt_import.operatingday, tt_import.trip_id, x.reinforcementnumber, x.vehiclenumber, tt_import.userstopcode, tt_import.passagesequencenumber, tt_import.pointorder, tt_import.targetarrivaltime, tt_import.targetdeparturetime, x.arrival as recordedarrivaltime, x.departure as recordeddeparturetime from (select trip_id, reinforcementnumber, vehiclenumber, userstopcode, passagesequencenumber, max(a.receive) as arrival, max(b.receive) as departure from kv6_import as a full outer join kv6_import as b using (trip_id, reinforcementnumber, userstopcode, passagesequencenumber, vehiclenumber) where a.messagetype = 'ARRIVAL' and b.messagetype = 'DEPARTURE' group by trip_id, reinforcementnumber, userstopcode, passagesequencenumber, vehiclenumber) as x right join tt_import using (trip_id, userstopcode, passagesequencenumber) order by trip_id, reinforcementnumber, pointorder) to '/home/skinkie/arriva/volledig-20240917.csv.gz' header;
```

Data:
https://download.stefan.konink.de/duckdb/kv6-20240917.log.gz
https://download.stefan.konink.de/duckdb/transittimes.csv.gz


### OS:

Linux

### DuckDB Version:

main

### DuckDB Client:

cli

### Hardware:

amd64

### Full Name:

Stefan de Konink

### Affiliation:

Stichting OpenGeo

### What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.

I have tested with a source build

### Did you include all relevant data sets for reproducing the issue?

No - Other reason (please specify in the issue body)

### Did you include all code required to reproduce the issue?

- [X] Yes, I have

### Did you include all relevant configuration (e.g., CPU architecture, Python version, Linux distribution) to reproduce the issue?

- [X] Yes, I have


Discussion / hints:
Thanks for the report and the reproducible example, I can confirm that this crashes.
Thanks for the report and the reproducible example, I can confirm that this crashes.

Fix patch:
diff --git a/src/include/duckdb/storage/table/segment_tree.hpp b/src/include/duckdb/storage/table/segment_tree.hpp
index e267d2e351eb..218cdac9b16f 100644
--- a/src/include/duckdb/storage/table/segment_tree.hpp
+++ b/src/include/duckdb/storage/table/segment_tree.hpp
@@ -145,6 +145,7 @@ class SegmentTree {
 		}
 		SegmentNode<T> node;
 		segment->index = nodes.size();
+		segment->next = nullptr;
 		node.row_start = segment->start;
 		node.node = std::move(segment);
 		nodes.push_back(std::move(node));
diff --git a/src/storage/table/row_group_collection.cpp b/src/storage/table/row_group_collection.cpp
index b0eb5022f75b..4dfb194921b6 100644
--- a/src/storage/table/row_group_collection.cpp
+++ b/src/storage/table/row_group_collection.cpp
@@ -962,8 +962,8 @@ unique_ptr<CheckpointTask> RowGroupCollection::GetCheckpointTask(CollectionCheck
 }
 
 void RowGroupCollection::Checkpoint(TableDataWriter &writer, TableStatistics &global_stats) {
-	auto segments = row_groups->MoveSegments();
 	auto l = row_groups->Lock();
+	auto segments = row_groups->MoveSegments(l);
 
 	CollectionCheckpointState checkpoint_state(*this, writer, segments, global_stats);
 


Test patch:
diff --git a/test/sql/storage/delete/delete_final_row_group.test b/test/sql/storage/delete/delete_final_row_group.test
new file mode 100644
index 000000000000..6dba3aca5923
--- /dev/null
+++ b/test/sql/storage/delete/delete_final_row_group.test
@@ -0,0 +1,42 @@
+# name: test/sql/storage/delete/delete_final_row_group.test
+# description: Test deleting the final row groups of a table
+# group: [delete]
+
+load __TEST_DIR__/delete_final_row_group.db
+
+statement ok
+CREATE TABLE integers AS SELECT * FROM range(0, 10000000) t(i);
+
+query I
+DELETE FROM integers WHERE i>=5000000
+----
+5000000
+
+query II
+SELECT COUNT(*), SUM(i) FROM integers
+----
+5000000	12499997500000
+
+
+statement ok
+ALTER TABLE integers ADD COLUMN j INTEGER
+
+query III
+SELECT COUNT(*), SUM(i), SUM(j) FROM integers
+----
+5000000	12499997500000	NULL
+
+statement ok
+UPDATE integers SET j=i+1
+
+query III
+SELECT COUNT(*), SUM(i), SUM(j) FROM integers
+----
+5000000	12499997500000	12500002500000
+
+restart
+
+query III
+SELECT COUNT(*), SUM(i), SUM(j) FROM integers
+----
+5000000	12499997500000	12500002500000
diff --git a/test/sqlite/sqllogic_command.cpp b/test/sqlite/sqllogic_command.cpp
index eb7636362900..527b91c6d115 100644
--- a/test/sqlite/sqllogic_command.cpp
+++ b/test/sqlite/sqllogic_command.cpp
@@ -492,14 +492,6 @@ void UnzipCommand::ExecuteInternal(ExecuteContext &context) const {
 		throw CatalogException("Cannot open the file \"%s\"", input_path);
 	}
 
-	// read the compressed data from the file
-	int64_t file_size = vfs.GetFileSize(*compressed_file_handle);
-	std::unique_ptr<char[]> compressed_buffer(new char[BUFFER_SIZE]);
-	int64_t bytes_read = vfs.Read(*compressed_file_handle, compressed_buffer.get(), BUFFER_SIZE);
-	if (bytes_read < file_size) {
-		throw CatalogException("Cannot read the file \"%s\"", input_path);
-	}
-
 	// output
 	FileOpenFlags out_flags(FileOpenFlags::FILE_FLAGS_FILE_CREATE | FileOpenFlags::FILE_FLAGS_WRITE);
 	auto output_file = vfs.OpenFile(extraction_path, out_flags);
@@ -507,9 +499,15 @@ void UnzipCommand::ExecuteInternal(ExecuteContext &context) const {
 		throw CatalogException("Cannot open the file \"%s\"", extraction_path);
 	}
 
-	int64_t bytes_written = vfs.Write(*output_file, compressed_buffer.get(), BUFFER_SIZE);
-	if (bytes_written < file_size) {
-		throw CatalogException("Cannot write the file \"%s\"", extraction_path);
+	// read the compressed data from the file
+	while (true) {
+		std::unique_ptr<char[]> compressed_buffer(new char[BUFFER_SIZE]);
+		int64_t bytes_read = vfs.Read(*compressed_file_handle, compressed_buffer.get(), BUFFER_SIZE);
+		if (bytes_read == 0) {
+			break;
+		}
+
+		vfs.Write(*output_file, compressed_buffer.get(), bytes_read);
 	}
 }