PostHog / PostHog/posthog

Saved query delete guard inspects one node but the delete removes every node

Open
#99,997 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
39.9k
Forks
3.4k
Avg merge
6h 51m
Merged PRs (30d)
232

Description

Bug description

The dependents guard that protects a saved query from being deleted out from under a live
dependent inspects a single node, while the delete itself removes every node the saved query
has. For a saved query with nodes in more than one DAG, a live dependent in another DAG passes
the guard, has its edge cascade-deleted, and then loses its source table.

No error is raised.

Mechanism

In products/data_modeling/backend/logic/saved_query_dag_sync.py:

  • line 311 — the guard resolves one node: Node.objects.filter(...).first()
  • lines 331-333 — the delete is a bulk queryset delete over every matching node

So the guard's scope and the delete's scope disagree. The guard answers "does this node have
dependents", and the delete acts on all of them.

Why it is reachable

A saved query can legitimately have nodes in several DAGs, so the asymmetry is not hypothetical.
Whether .first() returns the node whose dependents matter is arbitrary.

Suggested direction

Check dependents across every node the delete will touch, not one.

Worth doing red-first: a test with a saved query in two DAGs and a live dependent in the second
should fail on master today.

Note that tightening this will make some deletes that currently succeed start raising, so it
needs a decision about what the user sees when a cross-DAG dependent blocks a delete.

Notes

Static check on master today — both halves read in the same file. Not executed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in products/data_modeling/backend/logic/saved_query_dag_sync.py, reading the guard around line 311 and the bulk delete at lines 331-333. Add the described red-first case with a saved query in two DAGs and a live dependent in the second. Done means dependents are checked across every node the delete touches and the cross-DAG blocking behavior is decided and covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.