@@ -91,3 +91,51 @@ def inner(conn):
9191 )
9292
9393 await internal_db .execute_fn (inner )
94+
95+
96+ @pytest .mark .asyncio
97+ async def test_stale_catalog_entry_database_fix (tmp_path ):
98+ """
99+ Test for https://github.com/simonw/datasette/issues/2605
100+
101+ When the internal database persists across restarts and has entries in
102+ catalog_databases for databases that no longer exist, accessing the
103+ index page should not cause a 500 error (KeyError).
104+ """
105+ from datasette .app import Datasette
106+
107+ internal_db_path = str (tmp_path / "internal.db" )
108+ data_db_path = str (tmp_path / "data.db" )
109+
110+ # Create a data database file
111+ import sqlite3
112+
113+ conn = sqlite3 .connect (data_db_path )
114+ conn .execute ("CREATE TABLE test_table (id INTEGER PRIMARY KEY)" )
115+ conn .close ()
116+
117+ # First Datasette instance: with the data database and persistent internal db
118+ ds1 = Datasette (files = [data_db_path ], internal = internal_db_path )
119+ await ds1 .invoke_startup ()
120+
121+ # Access the index page to populate the internal catalog
122+ response = await ds1 .client .get ("/" )
123+ assert "data" in ds1 .databases
124+ assert response .status_code == 200
125+
126+ # Second Datasette instance: reusing internal.db but WITHOUT the data database
127+ # This simulates restarting Datasette after removing a database
128+ ds2 = Datasette (internal = internal_db_path )
129+ await ds2 .invoke_startup ()
130+
131+ # The database is not in ds2.databases
132+ assert "data" not in ds2 .databases
133+
134+ # Accessing the index page should NOT cause a 500 error
135+ # This is the bug: it currently raises KeyError when trying to
136+ # access ds.databases["data"] for the stale catalog entry
137+ response = await ds2 .client .get ("/" )
138+ assert response .status_code == 200 , (
139+ f"Index page should return 200, not { response .status_code } . "
140+ "This fails due to stale catalog entries causing KeyError."
141+ )
0 commit comments