Skip to content

[#12468] fix(lance): validate the identifier in ListNamespaces at schema level - #12469

Open
FANNG1 wants to merge 1 commit into
apache:mainfrom
FANNG1:fix-12468-lance-list-namespaces
Open

[#12468] fix(lance): validate the identifier in ListNamespaces at schema level#12469
FANNG1 wants to merge 1 commit into
apache:mainfrom
FANNG1:fix-12468-lance-list-namespaces

Conversation

@FANNG1

@FANNG1 FANNG1 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

GravitinoLanceNameSpaceOperations.listNamespaces now validates the identifier
in its two-level branch: it resolves the catalog with
loadAndValidateLakehouseCatalog and checks the schema with schemaExists
before returning the empty list. The schema check shared with namespaceExists
is extracted into a validateSchemaExists helper so both operations raise the
same NamespaceNotFoundException.

Returning an empty list at level 2 stays correct — a schema has no child
namespaces, only tables — the missing part was the existence check.

Why are the changes needed?

ListNamespaces returned HTTP 200 with {"namespaces":[]} for any two-level
identifier, without checking that it referred to anything real. That made a
child of a nonexistent parent look like it existed, while the parent itself
correctly failed:

GET /lance/v1/namespace/BOGUS_CATALOG%24BOGUS_SCHEMA/list?delimiter=%24
{"namespaces":[]}                                    <-- success

GET /lance/v1/namespace/BOGUS_CATALOG/list?delimiter=%24
{"error":"Catalog not found: BOGUS_CATALOG", ...}    <-- correctly fails

listNamespaces was also the only namespace operation without this check —
describeNamespace, namespaceExists, dropNamespace and createNamespace
all validate at level 2. Clients that probe a configured namespace path with
ListNamespaces (for example Apache Doris's Lance REST catalog, which probes
lance.namespace.parent at catalog-creation time) silently accepted a mistyped
schema and only failed much later on the first read.

ListTables was checked for the mirror-image gap and does not have one: it
requires exactly two levels, and ManagedTableOperations.listTables throws
NoSuchSchemaException for a nonexistent schema, which the exception mapper
turns into a 404.

Fix: #12468

Does this PR introduce any user-facing change?

Yes. ListNamespaces on a two-level identifier whose catalog or schema does not
exist now returns 404 NAMESPACE_NOT_FOUND instead of 200 with an empty list.
Listing a schema that does exist still returns an empty list as before.

How was this patch tested?

  • New unit test TestGravitinoLanceNameSpaceOperations (3 cases: existing
    schema returns an empty list; nonexistent schema returns 404; nonexistent
    catalog returns 404 at both one and two levels). Reverting the main-code
    change makes 2 of the 3 fail.
  • Extended LanceRESTServiceIT.testListNamespaces to cover the same three
    cases end to end against a running Lance REST service; passes.
  • ./gradlew :lance:lance-common:test :lance:lance-rest-server:test -PskipITs
    passes.

https://claude.ai/code/session_012J3xbmJ3pHcMuJfG7Sonr6

…at schema level

ListNamespaces returned an empty list for any two-level identifier without
checking that the catalog and schema exist, so a nonexistent path was
reported as an existing but empty namespace while its own one-level prefix
correctly failed. Validate the catalog and the schema before returning the
(correctly) empty list, reusing the helper that namespaceExists already uses.

Claude-Session: https://claude.ai/code/session_012J3xbmJ3pHcMuJfG7Sonr6
@github-actions

Copy link
Copy Markdown

Code Coverage Report

Overall Project 68.66% -0.16% 🟢
Files changed 1.41% 🔴

Module Coverage
aliyun 1.72% 🔴
api 49.31% 🟢
authorization-common 85.96% 🟢
aws 42.04% 🟢
azure 2.47% 🔴
catalog-common 9.92% 🔴
catalog-fileset 79.77% 🟢
catalog-glue 68.95% 🟢
catalog-hive 79.4% 🟢
catalog-jdbc-common 45.7% 🟢
catalog-jdbc-doris 81.8% 🟢
catalog-jdbc-mysql 79.33% 🟢
catalog-jdbc-postgresql 83.39% 🟢
catalog-jdbc-starrocks 79.16% 🟢
catalog-kafka 77.01% 🟢
catalog-lakehouse-generic 59.18% 🟢
catalog-lakehouse-hudi 79.1% 🟢
catalog-lakehouse-iceberg 85.86% 🟢
catalog-lakehouse-paimon 84.23% 🟢
catalog-model 77.72% 🟢
cli 44.48% 🟢
client-java 78.56% 🟢
common 52.75% 🟢
core 83.63% 🟢
filesystem-hadoop3 77.28% 🟢
flink 0.0% 🔴
flink-common 48.68% 🟢
flink-runtime 0.0% 🔴
gcp 14.12% 🔴
hadoop-auth 68.0% 🟢
hadoop-common 12.7% 🔴
hive-metastore-common 53.4% 🟢
iceberg-aliyun-bundle 0.0% 🔴
iceberg-common 64.75% 🟢
iceberg-rest-server 75.03% 🟢
idp-basic 86.02% 🟢
integration-test-common 0.0% 🔴
jobs 62.92% 🟢
lance-common 31.63% -7.64% 🔴
lance-rest-server 63.47% 🟢
lineage 53.02% 🟢
optimizer 83.24% 🟢
optimizer-api 21.95% 🔴
server 87.25% 🟢
server-common 79.41% 🟢
spark 28.57% 🔴
spark-common 45.89% 🟢
tencent 69.84% 🟢
trino-connector 40.29% 🟢
Files
Module File Coverage
lance-common GravitinoLanceNameSpaceOperations.java 1.41% 🔴

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.

[Bug report] Lance REST ListNamespaces returns success for a nonexistent two-level namespace

1 participant