From 63dd39d17208352dd88df7fdb85d0a4cfe700c62 Mon Sep 17 00:00:00 2001 From: Claudio Date: Sun, 10 May 2026 22:30:34 +0200 Subject: [PATCH] fix(nextcloud): NULL parent_id before deleting Folder rows on SourceRoot remove Folders have a self-referential parent_id FK with no ON DELETE rule. A flat DELETE of the whole subtree trips folders_parent_id_fkey because postgres checks the constraint per-row regardless of insertion / list order. Hard-removing 'Taco and Muli - 2024 onward' (35-folder subtree) returned 500 with ForeignKeyViolationError every attempt. Fix: UPDATE folders SET parent_id = NULL WHERE id IN (folder_ids) before the DELETE so the chain is broken cleanly. Same pattern used in prune_missing_photos for the same constraint. Co-Authored-By: Claude Opus 4.7 (1M context) --- backend/app/routers/nextcloud.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/backend/app/routers/nextcloud.py b/backend/app/routers/nextcloud.py index 552b1be..1461088 100644 --- a/backend/app/routers/nextcloud.py +++ b/backend/app/routers/nextcloud.py @@ -30,7 +30,7 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel -from sqlalchemy import delete, select +from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db @@ -332,6 +332,17 @@ async def delete_nextcloud_source_root( FolderShare.folder_type == 'folder', ) ) + # Folders have a self-referential parent_id FK with no + # ON DELETE rule. A flat DELETE of the whole subtree trips + # `folders_parent_id_fkey` because postgres checks the + # constraint per row, regardless of insertion / list order. + # NULL the parent_id on every folder we're about to delete + # first so the chain breaks cleanly. + await db.execute( + update(Folder) + .where(Folder.id.in_(folder_ids)) + .values(parent_id=None) + ) await db.execute(delete(Folder).where(Folder.id.in_(folder_ids))) await db.delete(sr)