Skip to content

fix(core): use upsert to prevent FK constraint violations in task DB#34977

Merged
FrozenPandaz merged 2 commits into
masterfrom
fix/db-fk-constraint-upsert
Mar 24, 2026
Merged

fix(core): use upsert to prevent FK constraint violations in task DB#34977
FrozenPandaz merged 2 commits into
masterfrom
fix/db-fk-constraint-upsert

Conversation

@leosvelperez
Copy link
Copy Markdown
Member

Current Behavior

INSERT OR REPLACE is used in task_details and cache_outputs tables. The bundled SQLite (libsqlite3-sys) is compiled with SQLITE_DEFAULT_FOREIGN_KEYS=1, so FK constraints are enforced by default. INSERT OR REPLACE does a DELETE + INSERT on PK conflict, and the implicit DELETE on task_details fails when child rows exist in task_history or cache_outputs:

NX   DB transaction error: SqliteFailure(Error { code: ConstraintViolation, extended_code: 787 }, Some("FOREIGN KEY constraint failed"))

This happens because record_task_details is called multiple times with the same hash across different code paths (hashTask, hashTasks, hashBatchTasks), and by the second call, child rows already reference that hash.

Expected Behavior

Use INSERT ... ON CONFLICT DO UPDATE (upsert) which updates the existing row in-place without deleting it. No DELETE means no FK violation, while preserving the same idempotent behavior the code relies on.

…aint violations

INSERT OR REPLACE does DELETE + INSERT on PK conflict. The bundled
SQLite has SQLITE_DEFAULT_FOREIGN_KEYS=1, so the implicit DELETE on
task_details fails when child rows exist in task_history or
cache_outputs. Use ON CONFLICT DO UPDATE (upsert) which updates
in-place without deleting.
@leosvelperez leosvelperez requested a review from a team as a code owner March 24, 2026 10:57
@leosvelperez leosvelperez requested a review from AgentEnder March 24, 2026 10:57
@leosvelperez leosvelperez self-assigned this Mar 24, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 24, 2026

Deploy Preview for nx-docs failed. Why did it fail? →

Name Link
🔨 Latest commit 9ab5ecc
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/69c272f3f3063f00082100d7

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 24, 2026

Deploy Preview for nx-dev ready!

Name Link
🔨 Latest commit 9ab5ecc
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/69c272f37eb98e000808f178
😎 Deploy Preview https://deploy-preview-34977--nx-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud Bot commented Mar 24, 2026

View your CI Pipeline Execution ↗ for commit 9ab5ecc

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 44m 27s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 8s View ↗
nx-cloud record -- pnpm nx conformance:check ✅ Succeeded 7s View ↗
nx build workspace-plugin ✅ Succeeded 2m 7s View ↗
nx-cloud record -- nx format:check ✅ Succeeded <1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-24 12:08:49 UTC

…aint violations

INSERT OR REPLACE does DELETE + INSERT on PK conflict. The bundled
SQLite has SQLITE_DEFAULT_FOREIGN_KEYS=1, so the implicit DELETE on
task_details fails when child rows exist in task_history or
cache_outputs. Use ON CONFLICT DO UPDATE (upsert) which updates
in-place without deleting. [Self-Healing CI Rerun]
Copy link
Copy Markdown
Contributor

@nx-cloud nx-cloud Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud has identified a flaky task in your failed CI:

🔂 Since the failure was identified as flaky, we triggered a CI rerun by adding an empty commit to this branch.

Nx Cloud View detailed reasoning in Nx Cloud ↗

🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.


🎓 Learn more about Self-Healing CI on nx.dev

@FrozenPandaz FrozenPandaz merged commit 95621cd into master Mar 24, 2026
19 of 23 checks passed
@FrozenPandaz FrozenPandaz deleted the fix/db-fk-constraint-upsert branch March 24, 2026 13:42
FrozenPandaz pushed a commit that referenced this pull request Mar 26, 2026
…34977)

## Current Behavior

`INSERT OR REPLACE` is used in `task_details` and `cache_outputs`
tables. The bundled SQLite (`libsqlite3-sys`) is compiled with
`SQLITE_DEFAULT_FOREIGN_KEYS=1`, so FK constraints are enforced by
default. `INSERT OR REPLACE` does a DELETE + INSERT on PK conflict, and
the implicit DELETE on `task_details` fails when child rows exist in
`task_history` or `cache_outputs`:

```
NX   DB transaction error: SqliteFailure(Error { code: ConstraintViolation, extended_code: 787 }, Some("FOREIGN KEY constraint failed"))
```

This happens because `record_task_details` is called multiple times with
the same hash across different code paths (`hashTask`, `hashTasks`,
`hashBatchTasks`), and by the second call, child rows already reference
that hash.

## Expected Behavior

Use `INSERT ... ON CONFLICT DO UPDATE` (upsert) which updates the
existing row in-place without deleting it. No DELETE means no FK
violation, while preserving the same idempotent behavior the code relies
on.

---------

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
(cherry picked from commit 95621cd)
@github-actions
Copy link
Copy Markdown
Contributor

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Mar 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants