Repository navigation
Recover DuckDB entity UUID conflicts without dropping or stalling - #1039
Merged
Intelli merged 1 commit intoOct 19, 2026
Merged
Conversation
A DuckDB unique-index conflict on co_entity_spawn.uuid can happen when the identity row was committed after the consumer transaction's snapshot began (or a delete is still visible to an older reader). - Entity removals: on the exact duplicate-UUID constraint error, roll back, start a fresh transaction and retry once; reuse the identity that is now visible. If it is still unresolved, drop only that removal and continue, instead of retrying the same event forever and blocking the queue. - Entity interactions: same refresh-and-retry, loading the existing identity so the interaction is recorded instead of dropped (PlayPro#1002 only dropped it). - Match the conflict on the event's own UUID, so other constraint errors are still retried and reported. - Reopen the entity_spawn prepared statement when DuckDB closed it after a constraint violation. - Summarize skipped records in one console warning every 5 minutes instead of a stack trace per event. Refs PlayPro#998 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #998 and #1002.
Since #1002, a DuckDB
Duplicate key "uuid: …"conflict onco_entity_spawnno longer stalls entity interactions. Two cases are still open.1. Entity removals still stall the queue
If an entity removal (death/despawn) hits the same conflict, it is retried on every pass and the events queued after it are held back. In a regression test against current master (and the 25.1 build), the conflicting removal and the event behind it were still queued after 20 consumer passes, with an error each pass.
This PR handles the exact duplicate-UUID error for the event's own UUID by rolling back, starting a fresh transaction and retrying once, reusing the identity if it is now visible. If it still conflicts, only that one removal is skipped and the queue continues. Every other constraint error (another UUID,
kill_rowid, I/O errors) is still retried and reported as before.2. Interactions: partial improvement, and a second cause I couldn't pin down
The same refresh-and-retry is applied to interactions. When the identity row was committed after the consumer's snapshot began, the retry finds it and the interaction is recorded instead of dropped.
On one production DuckDB server, though, interactions are dropped about 470 times a day across about 90 distinct entities, and the same UUID keeps failing for up to 25 minutes (up to 25 times). That doesn't look like a short snapshot race. The row seems to stay invisible to fresh transactions while its key is still in the unique index. One possibility is a deleted key lingering in DuckDB's ART index until checkpoint. For that case this PR still skips the interaction (same outcome as today), only more quietly. I don't know the root cause and would value your view.
Also
entity_spawnprepared statement when DuckDB closed it after a constraint violation.ErrorReporterstill receives each failure.Testing
src/testis ignored here. Current master passes 11 of the 18 shared tests; this branch passes all 20.🤖 Generated with Claude Code