Skip to content

Recover DuckDB entity UUID conflicts without dropping or stalling - #1039

Merged
Intelli merged 1 commit into
PlayPro:masterfrom
DarkChromaMC:fix/duckdb-entity-uuid-conflicts
Oct 19, 2026
Merged

Intelli merged 1 commit into
PlayPro:masterfrom
DarkChromaMC:fix/duckdb-entity-uuid-conflicts

Conversation

@DarkChromaMC

Copy link
Copy Markdown
Contributor

Follow-up to #998 and #1002.

Since #1002, a DuckDB Duplicate key "uuid: …" conflict on co_entity_spawn no 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

  • Reopens the entity_spawn prepared statement when DuckDB closed it after a constraint violation.
  • Replaces the per-event stack trace with one console summary every 5 minutes. ErrorReporter still receives each failure.
  • No behaviour change for SQLite, MySQL or ClickHouse.

Testing

  • 20 JUnit tests against a real DuckDB file and the real consumer. Only the JDBC connection is intercepted to create the conflict. They're on this branch rather than in the PR, since src/test is ignored here. Current master passes 11 of the 18 shared tests; this branch passes all 20.
  • Paper 26.3 test server with a bot: shearing, feeding, player kills and command kills were all logged, interactions were linked to their entity identities, removals were recorded, lookups worked and shutdown was clean.

🤖 Generated with Claude Code

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>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T10:38:39.427531Z ebe4225 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Intelli
Intelli merged commit dffa04f into PlayPro:master Oct 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants