unitycatalog / unitycatalog/unitycatalog
Concurrent creates of the same table name persist duplicate rows, permanently breaking that name
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 3.5k
- Forks
- 672
- Avg merge
- 6d 16h
- Merged PRs (30d)
- 30
Description
Describe the bug
uc_tables has no unique constraint on (schema_id, name) -- TableInfoDAO declares only
@Index(name = "idx_name", columnList = "name") -- and TableRepository.createTable checks for an
existing name and then inserts in separate statements. Two concurrent creates of the same table name
therefore both pass the check and both insert, leaving two rows with the same (schema_id, name).
Every later lookup of that name fails, because the repository resolves a table by name with
Query.uniqueResult(), which throws NonUniqueResultException on two rows: getTable answers 500,
and so does deleteTable, so the duplicate cannot be removed through the API and the name stays
broken. The Iceberg REST endpoints resolve the same way through findTableOrThrow.
The same check-then-insert shape, with no unique constraint behind the column it checks, appears
elsewhere: SchemaRepository.createSchema (uc_schemas declares no constraints at all),
ModelRepository.createRegisteredModel (uc_registered_models has a plain name index),
StagingTableRepository, and UserRepository.createUser, whose email check has no constraint behind
it -- uc_users constrains external_id only. I have only reproduced the table case.
To Reproduce
Steps to reproduce the behavior:
- Start the server and create a catalog and a schema.
- Send two
POST /api/2.1/unity-catalog/tablesrequests for the same table name at the same moment
(two threads released by a barrier). Both answer 200, with differenttable_ids -- reproduced on
the first attempt againstmainat 58d5c7b:
[created:20b45618-2046-4c1e-83cd-8fcbcaf12cfa, created:8dc1d9a9-23e9-40ec-b936-31d44b94399f] GET /api/2.1/unity-catalog/tables/{catalog}.{schema}.{table}now answers
500 INTERNAL,"message": "Failed to get table: Query did not return a unique result: 2 results were returned"
(fromTableRepository.getTable).DELETEon the same name answers500 INTERNAL,
"message": "Failed to delete table: Query did not return a unique result: 2 results were returned"
(fromTableRepository.deleteTable), so the rows cannot be removed through the API. The name stays
unusable until the database is edited directly.
Expected behavior
One of the two creates succeeds and the other fails with TABLE_ALREADY_EXISTS, which is what a
single create against an existing name already returns. A duplicate (schema_id, name) should not be
representable in the schema.
System [please complete the following information]:
- OS: macOS 15, server built from
mainat 58d5c7b (H2 store, but the missing constraint is not store-specific)
Additional context
A unique constraint on (schema_id, name) would close it at the source, and would let
createTable translate the constraint violation into TABLE_ALREADY_EXISTS instead of relying on
the preceding read. That implies a schema change for existing databases, which is adjacent to the
"database schema upgrades" item on the roadmap, so I am filing this rather than sending a patch --
happy to implement whichever direction the maintainers prefer.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with TableInfoDAO and TableRepository.createTable, getTable, and deleteTable, then compare the check-then-insert paths in SchemaRepository, ModelRepository, StagingTableRepository, and UserRepository. Reproduce the two-thread table creation against the H2 store and inspect the database schema upgrades roadmap. Done means duplicate names are prevented and the losing create reports TABLE_ALREADY_EXISTS without leaving lookups or deletion broken.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, sql
- Domain
- backend-api-design, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100