Bug Description
Deleting a flow raises a psycopg.errors.ForeignKeyViolation IntegrityError when the flow has associated
execution traces (records in the trace and span tables). The deletion fails inside cascade_delete_flow
and surfaces as a 500 error in the ASGI application.
Error log:
Unable to cascade delete flow: 21e3cc42-cada-492b-8183-5fca183f65cd
IntegrityError: (psycopg.errors.ForeignKeyViolation) update or delete on table "trace"
violates foreign key constraint "span_trace_id_fkey" on table "span"
DETAIL: Key (id)=(e306f1a8-94d5-47a6-8206-579ed2c82203) is still referenced from table "span".
There are two compounding root causes:
Root Cause 1 — Missing ON DELETE CASCADE on span.trace_id FK at the database level
The migration 3478f0bd6ccb_add_trace_and_span_tables.py creates the span table's FK to trace
without ondelete="CASCADE":
# span → trace: MISSING ondelete="CASCADE"
sa.ForeignKeyConstraint(["trace_id"], ["trace.id"]),
# trace → flow: correctly has CASCADE
sa.ForeignKeyConstraint(["flow_id"], ["flow.id"], ondelete="CASCADE"),
When PostgreSQL cascades the flow → trace delete (which works), it attempts to delete trace rows next,
but fails because span records still reference them and the FK has no cascade rule.
Root Cause 2 — cascade_delete_flow never explicitly deletes trace or span records
cascade_delete_flow in src/backend/base/langflow/api/utils/core.py uses raw SQL delete() statements
and relies entirely on the database-level FK cascade from flow → trace → span. However:
- Raw SQL bypasses SQLAlchemy ORM cascade (
cascade="all, delete-orphan" defined on
TraceTable.spans), so the ORM safety net never fires.
- The function explicitly deletes
MessageTable, TransactionTable, VertexBuildTable, and
FlowVersion before deleting Flow, but never handles SpanTable or TraceTable,
leaving them entirely dependent on the broken DB-level cascade chain.
Proposed Fix Options
| Option |
Description |
| A (Application-level) |
Add explicit delete(SpanTable) and delete(TraceTable) statements to cascade_delete_flow before deleting Flow, matching the existing pattern for other child tables. |
| B (Database-level) |
Add a new Alembic migration to alter span.trace_id FK to include ON DELETE CASCADE, completing the cascade chain at the DB level. |
Option A is immediately safe for both SQLite and PostgreSQL and requires no schema migration.
Option B is the more robust long-term solution and can be applied alongside Option A for defence in depth.
Affected Files
| File |
Issue |
src/backend/base/langflow/api/utils/core.py |
cascade_delete_flow missing explicit deletes for SpanTable and TraceTable |
src/backend/base/langflow/alembic/versions/3478f0bd6ccb_add_trace_and_span_tables.py |
span.trace_id FK created without ondelete="CASCADE" |
src/backend/base/langflow/services/database/models/traces/model.py |
ORM-level cascade defined but bypassed by raw SQL in cascade_delete_flow |
Reproduction
- Run Langflow against a PostgreSQL database.
- Apply all migrations up to and including
59a272d6669a — trace.flow_id will have CASCADE,
but span.trace_id will not.
- Execute at least one flow that generates traces (creates rows in
trace and span).
- Delete that flow via the UI or API:
DELETE /api/v1/flows/{flow_id}.
- Observe the 500 error and
ForeignKeyViolation in the application logs.
Expected behavior
Deleting a flow should atomically remove all child records in dependency order without any
IntegrityError:
This is consistent with how other child tables (MessageTable, TransactionTable, etc.) are
already handled by cascade_delete_flow.
Who can help?
No response
Operating System
Openshift
Langflow Version
1.8.1
Python Version
3.12
Screenshot
No response
Flow File
No response
Bug Description
Deleting a flow raises a
psycopg.errors.ForeignKeyViolationIntegrityErrorwhen the flow has associatedexecution traces (records in the
traceandspantables). The deletion fails insidecascade_delete_flowand surfaces as a 500 error in the ASGI application.
Error log:
There are two compounding root causes:
Root Cause 1 — Missing
ON DELETE CASCADEonspan.trace_idFK at the database levelThe migration
3478f0bd6ccb_add_trace_and_span_tables.pycreates thespantable's FK totracewithout
ondelete="CASCADE":When PostgreSQL cascades the
flow → tracedelete (which works), it attempts to deletetracerows next,but fails because
spanrecords still reference them and the FK has no cascade rule.Root Cause 2 —
cascade_delete_flownever explicitly deletestraceorspanrecordscascade_delete_flowinsrc/backend/base/langflow/api/utils/core.pyuses raw SQLdelete()statementsand relies entirely on the database-level FK cascade from
flow → trace → span. However:cascade="all, delete-orphan"defined onTraceTable.spans), so the ORM safety net never fires.MessageTable,TransactionTable,VertexBuildTable, andFlowVersionbefore deletingFlow, but never handlesSpanTableorTraceTable,leaving them entirely dependent on the broken DB-level cascade chain.
Proposed Fix Options
delete(SpanTable)anddelete(TraceTable)statements tocascade_delete_flowbefore deletingFlow, matching the existing pattern for other child tables.span.trace_idFK to includeON DELETE CASCADE, completing the cascade chain at the DB level.Option A is immediately safe for both SQLite and PostgreSQL and requires no schema migration.
Option B is the more robust long-term solution and can be applied alongside Option A for defence in depth.
Affected Files
src/backend/base/langflow/api/utils/core.pycascade_delete_flowmissing explicit deletes forSpanTableandTraceTablesrc/backend/base/langflow/alembic/versions/3478f0bd6ccb_add_trace_and_span_tables.pyspan.trace_idFK created withoutondelete="CASCADE"src/backend/base/langflow/services/database/models/traces/model.pycascade_delete_flowReproduction
59a272d6669a—trace.flow_idwill haveCASCADE,but
span.trace_idwill not.traceandspan).DELETE /api/v1/flows/{flow_id}.ForeignKeyViolationin the application logs.Expected behavior
Deleting a flow should atomically remove all child records in dependency order without any
IntegrityError:This is consistent with how other child tables (
MessageTable,TransactionTable, etc.) arealready handled by
cascade_delete_flow.Who can help?
No response
Operating System
Openshift
Langflow Version
1.8.1
Python Version
3.12
Screenshot
No response
Flow File
No response