From 43e70de983401301fd623bb7fb8d88c33277162d Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Thu, 22 Oct 2026 07:37:24 +0100 Subject: [PATCH] Delete a bot file's chunks with the file ON DELETE CASCADE only fires when PRAGMA foreign_keys is on, and only src/server.ts turns it on. A script or CLI process deleting a bot file therefore left every bot_file_chunks row behind, and the next `bun run db:schema` failed with Foreign key violations after schema sync: bot_file_chunks -> bot_files deleteBotFile and purgeStorage now delete the chunks themselves, so the cascade is no longer load-bearing and a maintenance script behaves like the server. --- src/functions/backend/db/bot-files/delete-bot-file.ts | 7 +++++++ src/functions/backend/db/bot-files/purge-storage.ts | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/functions/backend/db/bot-files/delete-bot-file.ts b/src/functions/backend/db/bot-files/delete-bot-file.ts index e58c32c..7700955 100644 --- a/src/functions/backend/db/bot-files/delete-bot-file.ts +++ b/src/functions/backend/db/bot-files/delete-bot-file.ts @@ -33,6 +33,13 @@ export default async function deleteBotFile({ scopes, file_id }: Params) { } await BunSQLite.sql({ sql: `DELETE FROM bot_file_vectors WHERE file_id = ?`, values: [file.id] }); + /** + * Deleted here rather than left to the schema's cascade: SQLite has + * foreign keys off per connection unless `enableForeignKeys` ran, and + * a script or CLI process that deletes a file would otherwise leave + * its chunks behind, which then fail the next schema sync. + */ + await BunSQLite.sql({ sql: `DELETE FROM bot_file_chunks WHERE file_id = ?`, values: [file.id] }); await BunSQLite.sql({ sql: `DELETE FROM bot_files WHERE id = ?`, values: [file.id] }); /** * Its pending ingestion would only find nothing left. diff --git a/src/functions/backend/db/bot-files/purge-storage.ts b/src/functions/backend/db/bot-files/purge-storage.ts index 5d4c91d..46d545d 100644 --- a/src/functions/backend/db/bot-files/purge-storage.ts +++ b/src/functions/backend/db/bot-files/purge-storage.ts @@ -59,6 +59,17 @@ export default async function purgeStorage({ scope, owner_id, media_ids }: Param values: [scope, owner_id], }).catch(() => {}); + /** + * Deleted here rather than left to the cascade, since SQLite has + * foreign keys off per connection unless `enableForeignKeys` ran (a + * script or CLI process never does), and a chunk left behind fails + * the next schema sync. + */ + await BunSQLite.sql({ + sql: `DELETE FROM bot_file_chunks WHERE scope = ? AND owner_id = ?`, + values: [scope, owner_id], + }).catch(() => {}); + /** * Usually gone already, with the bot or workspace (the cascade). */