DELETE /api/cases/{id} returns 500 (FK constraint failure) — regression from FK enforcement in d0723c9 #101

Closed
opened 2026-08-14 07:05:51 +00:00 by Mark · 5 comments
Owner

Regression introduced by d0723c9 (FK enforcement + ondelete=CASCADE on organization child FKs), found by post-deploy probe of #95.

Repro

  1. Checkout origin/main HEAD b81dc67 (or any tree including d0723c9).
  2. pytest tests/integration/test_integration_concurrent.py::TestConcurrentDeletion::test_delete_while_reading — fails 3/3 solo and in combined run.
  3. Same test on pre-fix baseline d9bbe4d — passes 3/3 solo and in combined run.

Actual

DELETE /api/cases/1 returns HTTP 500; traceback shows PendingRollbackError wrapping sqlite3.IntegrityError: FOREIGN KEY constraint failed.

Expected

Case deletion succeeds with dependent rows cleaned up (200/204, no 500).

Root cause

PRAGMA foreign_keys=ON is now enabled in the test SQLite engine, but the case-delete path still violates an FK not covered by the CASCADE additions (OrganizationEmail/Phone/Domain) from d0723c9. Production Postgres always enforces FKs, so this endpoint is likely broken in prod too — it was masked before only by the FK-off test engine. Not caught by CI because the integration suite runs with continue-on-error.

Filed from kanban card t_311f173d (post-deploy probe of #95).

Regression introduced by d0723c9 (FK enforcement + ondelete=CASCADE on organization child FKs), found by post-deploy probe of #95. ## Repro 1. Checkout origin/main HEAD b81dc67 (or any tree including d0723c9). 2. `pytest tests/integration/test_integration_concurrent.py::TestConcurrentDeletion::test_delete_while_reading` — **fails 3/3** solo and in combined run. 3. Same test on pre-fix baseline d9bbe4d — **passes 3/3** solo and in combined run. ## Actual `DELETE /api/cases/1` returns **HTTP 500**; traceback shows `PendingRollbackError` wrapping `sqlite3.IntegrityError: FOREIGN KEY constraint failed`. ## Expected Case deletion succeeds with dependent rows cleaned up (200/204, no 500). ## Root cause PRAGMA foreign_keys=ON is now enabled in the test SQLite engine, but the case-delete path still violates an FK not covered by the CASCADE additions (OrganizationEmail/Phone/Domain) from d0723c9. Production Postgres always enforces FKs, so this endpoint is likely broken in prod too — it was masked before only by the FK-off test engine. Not caught by CI because the integration suite runs with continue-on-error. Filed from kanban card t_311f173d (post-deploy probe of #95).
Author
Owner

REOPENED — FALSE-POSITIVE CLOSE (reporter lane, kanban t_8151e5f3)

Issue was marked closed 2026-08-20T03:12:23Z but the fix never landed on the default branch (main).

Verified:

  1. Issue state=closed, carried labels [blocked:preflight, bug, triage-approved].
  2. Fix exists ONLY on unmerged branch/PR: fix commit aaed2de on branch fix/101-fk-cascade; PR #104 (fix/101-fk-cascade -> main) = OPEN, merged=False, mergeable=True.
  3. origin/main HEAD is still b81dc67 (pre-fix). Recent-main scan shows 0 commits referencing #101. Fix migration f101c4scd0a1_add_ondelete_cascade_case_membership_fk.py exists only on the fix branch, NOT on main.

Impact: Deployed/default code still returns HTTP 500 on DELETE /api/cases/{id} (FK constraint failure). This is a functional bug still live in production.

Fix quality (verified): regression test TestConcurrentDeletion::test_delete_while_reading passes; 47 new tests in test_api_cases.py pass on the fix branch. Fix is sound.

Action needed: merge PR #104 to main (or route fix/101-fk-cascade through the fix pipeline), then re-verify and close. Re-added triage-approved + bug; dropped blocked:preflight (fix verified, no longer preflight-blocking).

REOPENED — FALSE-POSITIVE CLOSE (reporter lane, kanban t_8151e5f3) Issue was marked closed 2026-08-20T03:12:23Z but the fix never landed on the default branch (main). Verified: 1. Issue state=closed, carried labels [blocked:preflight, bug, triage-approved]. 2. Fix exists ONLY on unmerged branch/PR: fix commit aaed2de on branch fix/101-fk-cascade; PR #104 (fix/101-fk-cascade -> main) = OPEN, merged=False, mergeable=True. 3. origin/main HEAD is still b81dc67 (pre-fix). Recent-main scan shows 0 commits referencing #101. Fix migration f101c4scd0a1_add_ondelete_cascade_case_membership_fk.py exists only on the fix branch, NOT on main. Impact: Deployed/default code still returns HTTP 500 on DELETE /api/cases/{id} (FK constraint failure). This is a functional bug still live in production. Fix quality (verified): regression test TestConcurrentDeletion::test_delete_while_reading passes; 47 new tests in test_api_cases.py pass on the fix branch. Fix is sound. Action needed: merge PR #104 to main (or route fix/101-fk-cascade through the fix pipeline), then re-verify and close. Re-added triage-approved + bug; dropped blocked:preflight (fix verified, no longer preflight-blocking).
Author
Owner

kilo-gsd-runner substrate check: Mark/osint-hub pre-dispatch gate blocks on residue worktree at .worktrees/t_5df1a1a4 (uncommitted changes against branch fix/annotation-tidy-t_5df1a1a4, pushed commits 7e9a485 / 9931443 / e7f79ba). Owning kanban card t_5df1a1a4 is done since 2026-09-06 with PR #118 in review. Issue-side tooling state, not a #101 concern. No kilo run dispatched; substrate otherwise clean (no live tmux, no live kilo run pid, no in-progress label, no commit referencing #101).

kilo-gsd-runner substrate check: Mark/osint-hub pre-dispatch gate blocks on residue worktree at .worktrees/t_5df1a1a4 (uncommitted changes against branch fix/annotation-tidy-t_5df1a1a4, pushed commits 7e9a485 / 9931443 / e7f79ba). Owning kanban card t_5df1a1a4 is `done` since 2026-09-06 with PR #118 in review. Issue-side tooling state, not a #101 concern. No kilo run dispatched; substrate otherwise clean (no live tmux, no live kilo run pid, no in-progress label, no commit referencing #101).
Author
Owner

kilo-gsd-runner launcher re-dispatch attempt (kanban t_67f4888d) — preflight block at 2026-09-09 12:09 PDT.

A live kilo-gsd.py run is already in progress against this issue: tmux session kilo-gsd-osint-hub-101-bugfix is running Phase 9 Bugfix on retry 2/3 after a Verify-gate failure (452 mypy errors). Branch fix/101-fk-cascade is at a68dafa, 2 commits ahead of origin/main (0af650a "fix(#101): case_delete FK regression..." + a68dafa "fix(lint): add noqa..."). Monitor tmux kilo-monitor-osint-hub-101 is live; log at ~/.hermes/logs/kilo-monitor/osint-hub-101-fixup.log.

The pre-dispatch gate (.gsd/gates/pre-dispatch.sh 101) sees the live run's in-flight edits on backend/app/models.py and backend/app/modules/base.py as "dirty paths outside .gsd/,.venv/,.kilo/" and exits 1. Per the kilo-gsd-runner contract, an alive substrate signal = lock held for cause; parallel dispatch would 2-write the same branch. The launcher is blocking its card (kind=capability) until the existing run lands or times out.

No action requested on the issue itself — this is informational so a human reviewer who sees another dispatch attempt doesn't escalate.

Launcher run id: 15055. Kanban card: t_67f4888d.

kilo-gsd-runner launcher re-dispatch attempt (kanban t_67f4888d) — preflight block at 2026-09-09 12:09 PDT. A live kilo-gsd.py run is already in progress against this issue: tmux session `kilo-gsd-osint-hub-101-bugfix` is running Phase 9 Bugfix on retry 2/3 after a Verify-gate failure (452 mypy errors). Branch `fix/101-fk-cascade` is at a68dafa, 2 commits ahead of origin/main (0af650a "fix(#101): case_delete FK regression..." + a68dafa "fix(lint): add noqa..."). Monitor tmux `kilo-monitor-osint-hub-101` is live; log at ~/.hermes/logs/kilo-monitor/osint-hub-101-fixup.log. The pre-dispatch gate (`.gsd/gates/pre-dispatch.sh 101`) sees the live run's in-flight edits on backend/app/models.py and backend/app/modules/base.py as "dirty paths outside .gsd/,.venv/,.kilo/" and exits 1. Per the kilo-gsd-runner contract, an alive substrate signal = lock held for cause; parallel dispatch would 2-write the same branch. The launcher is blocking its card (`kind=capability`) until the existing run lands or times out. No action requested on the issue itself — this is informational so a human reviewer who sees another dispatch attempt doesn't escalate. Launcher run id: 15055. Kanban card: t_67f4888d.
Author
Owner

kanban-launcher note: launcher attempt 3 on t_67f4888d blocked because live kilo-gsd.py run 15046 (tmux kilo-monitor-osint-hub-101 + run-loop kilo-gsd-osint-hub-101-bugfix) holds the #101 substrate on branch fix/101-fk-cascade. Branch is 2 commits ahead of origin/main; bugfix phase is on slice 3/3 (62 unit tests passing, targeting 452 mypy errors). My card is dependency-linked to t_de43d1c5 and will auto-promote when that run lands. Out of scope for the launcher to interfere with the live run; the watcher owns the terminal signal.

kanban-launcher note: launcher attempt 3 on t_67f4888d blocked because live kilo-gsd.py run 15046 (tmux kilo-monitor-osint-hub-101 + run-loop kilo-gsd-osint-hub-101-bugfix) holds the #101 substrate on branch fix/101-fk-cascade. Branch is 2 commits ahead of origin/main; bugfix phase is on slice 3/3 (62 unit tests passing, targeting 452 mypy errors). My card is dependency-linked to t_de43d1c5 and will auto-promote when that run lands. Out of scope for the launcher to interfere with the live run; the watcher owns the terminal signal.
Mark closed this issue 2026-09-10 02:27:44 +00:00
Author
Owner

Fix landed in 93791d4182 via PR #104.

Fix landed in 93791d418263b6c57d430eaaf1e49e55000ad118 via PR #104.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/osint-hub#101
No description provided.