Skip to content

S3Tables: raise TableAlreadyExists instead of building it - #10141

Open
Zuhef wants to merge 1 commit into
getmoto:masterfrom
Zuhef:fix/alpha-s3tables-table-already-exists
Open

S3Tables: raise TableAlreadyExists instead of building it#10141
Zuhef wants to merge 1 commit into
getmoto:masterfrom
Zuhef:fix/alpha-s3tables-table-already-exists

Conversation

@Zuhef

@Zuhef Zuhef commented Jul 30, 2026

Copy link
Copy Markdown

create_table builds TableAlreadyExists without raising it, so the duplicate-name guard has no effect:

if name in ns.tables:
    TableAlreadyExists()
table = Table(...)
ns.tables[name] = table

The two raise NotFoundException(...) guards a few lines above are correct, which is what makes this one stand out.

The result is that creating a table with a name that already exists succeeds and replaces the existing table rather than being rejected:

>>> client.create_table(tableBucketARN=arn, namespace="ns", name="t", format="ICEBERG")
>>> client.get_table(tableBucketARN=arn, namespace="ns", name="t")["versionToken"]
'2558ff5603108fb4f052'
>>> client.create_table(tableBucketARN=arn, namespace="ns", name="t", format="ICEBERG")   # accepted
>>> client.get_table(tableBucketARN=arn, namespace="ns", name="t")["versionToken"]
'0897d5495b52d1cac9ff'

Both versionToken and createdAt change, so it is a replacement rather than a no-op, and list_tables still reports one table. Any state the first table had is gone.

Adding the raise makes it return the ConflictException that the existing TableAlreadyExists class was already written for, with its message "A table with an identical name already exists in the namespace.".

Added test_create_table_with_an_existing_name, which fails without the change with Failed: DID NOT RAISE ConflictException. It follows the client.exceptions.<Name> style already used in this file.

tests/test_s3tables passes (37), ruff format is clean, mypy reports nothing, and ruff check moto/s3tables tests/test_s3tables finds the same 4 pre-existing issues before and after my change.

I did not verify the exact wording or code that real S3 Tables returns for this. The message and exception class are moto's own, already present in moto/s3tables/exceptions.py; I only made the existing guard effective.

create_table constructed the exception without raising it, so creating a table whose name already exists was accepted and replaced the existing table instead of returning a ConflictException.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant