You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Purpose of this issue: document a known quirk and open discussion on how (or whether) to guard against it — not to mandate a specific fix.
Suggested priority: P3 (usability / minor). No data loss, no blocked functionality, and a trivial workaround exists (remove the property). The cost is purely a confusing first-run experience. Could be argued up to P2 given it's demo-visible and hits anyone copying a hive/jdbc example.
On the lakehouse-iceberg catalog with catalog-backend=rest, the warehouse property is a catalog selector (a name) — it's forwarded to the remote IRC as GET /v1/config?warehouse=<value>. On the hive/jdbc backends the same property is a storage-location URI. Because the name means two different things by backend, users copying a hive/jdbc example naturally set a URI like warehouse: "s3://warehouse/" on a REST catalog.
The catalog is then created without complaint (the value is accepted, never validated), and the failure is deferred to the first table/namespace operation:
org.apache.iceberg.exceptions.NoSuchWarehouseException:
Couldn't find Iceberg configuration for catalog s3://warehouse/
The confusion is best seen as a matrix over two dimensions — backend (rest vs hive/jdbc) and whether warehouseis a URI, a name, or omitted — comparing what the user intends against the outcome:
Backend
warehouse
User intends
What it means here
Outcome
hive/jdbc
s3://warehouse/ (URI)
"where data lives"
storage location ✅ matches
✅ Works — correct usage
hive/jdbc
(omitted)
"use a default"
required, no default
❌ Rejected at create, clear msg: The 'warehouse' parameter must have a value.
rest
(omitted)
"just connect"
default catalog
✅ Works — recommended REST setup
rest
sales (a name)
"use my sales catalog"
catalog selector ✅ matches
✅ Works — multi-catalog usage
rest
s3://warehouse/ (URI)
"where data lives" (copied from hive/jdbc)
catalog name to look up ✗ mismatch
❌ The trap. Create → 200; first op → NoSuchWarehouseException: Couldn't find Iceberg configuration for catalog s3://warehouse/
rest
"" (empty)
(accidental)
blank → default catalog
✅ Works
The whole issue is one cell — rest + URI. It's dangerous because on hive/jdbc that same URI value is required and correct, so the user's instinct ("warehouse = my S3 path") is right everywhere except here — and unlike the hive/jdbc mistake, this one is silently accepted at create and only fails later.
Flow (what actually happens)
flowchart TD
U(["User creates a lakehouse-iceberg catalog<br/>with a 'warehouse' value"]) --> B{catalog-backend?}
B -->|hive / jdbc| H["'warehouse' = STORAGE LOCATION"]
H --> HV{value provided?}
HV -->|"s3://warehouse/ (URI)"| HOK["✅ used as the data location — matches intent"]
HV -->|omitted| HERR["❌ rejected at CREATE, clear message:<br/>'The warehouse parameter must have a value'"]
B -->|rest| R["Gravitino forwards the value verbatim:<br/>GET /v1/config?warehouse=VALUE"]
R --> IRC["IRC interprets VALUE as a CATALOG NAME to look up"]
IRC --> F{name resolves?}
F -->|"omitted → default, or real name e.g. 'sales'"| ROK["✅ 200 ConfigResponse — catalog selected"]
F -->|"s3://warehouse/ (URI) — no such name"| RERR["❌ 404 → NoSuchWarehouseException<br/>CREATE returned 200; surfaces only on first use"]
classDef good fill:#e6ffed,stroke:#2ea043,color:#003300;
classDef bad fill:#ffebe9,stroke:#cf222e,color:#330000;
class HOK,ROK good;
class HERR,RERR bad;
Loading
The same s3://warehouse/ edge lands on green on the hive/jdbc side and red on the rest side — that mirror is the bug in one picture.
Reproduction (Docker quickstart)
Environment: apache/gravitino:latest (native API on :8090) + apache/gravitino-iceberg-rest:latest (IRC on :9001), as reported on the gravitino-irc-quickstart setup.
# Register a REST-backend catalog with a URI-shaped warehouse (the natural mistake# when copying a jdbc/hive example). This SUCCEEDS — nothing rejects it.
curl -s -X POST http://localhost:8090/api/metalakes/v3check/catalogs \
-H 'Accept: application/vnd.gravitino.v1+json' \
-H 'Content-Type: application/json' \
-d '{ "name": "irc_probe", "type": "RELATIONAL", "provider": "lakehouse-iceberg", "comment": "probe with URI warehouse", "properties": { "catalog-backend": "rest", "uri": "http://gravitino-irc:9001/iceberg", "warehouse": "s3://warehouse/" } }'# -> HTTP 200, catalog created.# Any subsequent operation triggers the IRC handshake and fails:
curl -s http://localhost:8090/api/metalakes/v3check/catalogs/irc_probe/schemas
# -> {"code":1006,"type":"NoSuchWarehouseException",# "message":"... Couldn't find Iceberg configuration for catalog s3://warehouse/"}# Removing 'warehouse' (or setting it to a real catalog name) works:
curl -s -X POST http://localhost:8090/api/metalakes/v3check/catalogs \
-H 'Accept: application/vnd.gravitino.v1+json' \
-H 'Content-Type: application/json' \
-d '{ "name": "irc_probe_ok", "type": "RELATIONAL", "provider": "lakehouse-iceberg", "properties": { "catalog-backend": "rest", "uri": "http://gravitino-irc:9001/iceberg" } }'
curl -s http://localhost:8090/api/metalakes/v3check/catalogs/irc_probe_ok/schemas # -> 200
Tests that expose the issue
The server-side behavior is already covered — a URI warehouse is just another unknown catalog name and returns 404 (which the Iceberg REST client rethrows as NoSuchWarehouseException). Adding the URI case to the existing parameterized test makes it explicit:
Verified locally: the added "s3://warehouse/" case passes (returns 404) unchanged, confirming the value is treated as a catalog name, not a location.
Related: #5756 made warehouse optional for REST (fixed); #9810 proposes hiding it in the Web UI; PR #9811 documented the distinction. This issue covers the remaining gap — the REST-API / catalog-init path gives no runtime hint when a URI-shaped value is used.
How should we improve?
Filing to surface the quirk and gather maintainer input. Some options, in ascending effort / intrusiveness:
Option A — Improve the error message only. Catch NoSuchWarehouseException on the REST path and append: "on the REST backend, warehouse selects a catalog by name; remove it or set a catalog name." Low effort, but the hint arrives late (first operation, not creation) and threads through Iceberg's exception.
Option B — WARN at catalog init when warehouse is URI-shaped. In the branch that already special-cases REST (IcebergCatalogWrapper.java:93):
} elseif (IcebergCatalogBackend.REST.equals(catalogBackend)) {
Stringwarehouse = icebergConfig.get(IcebergConfig.CATALOG_WAREHOUSE);
if (StringUtils.isNotBlank(warehouse) && warehouse.contains("://")) {
LOG.warn(
"The 'warehouse' value '{}' looks like a storage-location URI, but for the REST "
+ "catalog backend 'warehouse' selects a catalog by name. It is sent to the Iceberg "
+ "REST server as a catalog selector and will likely fail with "
+ "NoSuchWarehouseException. Remove 'warehouse' to use the default catalog, or set "
+ "it to the target catalog's name.",
warehouse);
}
}
Non-breaking, fires at creation, correctly scoped (hive/jdbc take the other branch). Pairs with a unit test asserting construction succeeds (no throw) plus the URI case in TestIcebergConfig.
Option C — Reject a URI-shaped warehouse at creation. Fail fast with a clear message. Best UX for the common case, butwarehouse is a server-defined opaque identifier per the Iceberg REST spec, and some non-Gravitino IRC servers legitimately use URI/ARN-shaped identifiers — a hard reject risks breaking valid federation.
Leaning toward Option B as the smallest non-breaking change that fires early and gives the exact hint the raw error omits — while avoiding Option C's risk to the legitimate opaque-identifier case. But the intent here is to document the quirk and discuss; happy to go with whatever the maintainers prefer (including doc-only, since PR #9811 already covers part of it).
What would you like to be improved?
Purpose of this issue: document a known quirk and open discussion on how (or whether) to guard against it — not to mandate a specific fix.
Suggested priority: P3 (usability /
minor). No data loss, no blocked functionality, and a trivial workaround exists (remove the property). The cost is purely a confusing first-run experience. Could be argued up to P2 given it's demo-visible and hits anyone copying a hive/jdbc example.On the
lakehouse-icebergcatalog withcatalog-backend=rest, thewarehouseproperty is a catalog selector (a name) — it's forwarded to the remote IRC asGET /v1/config?warehouse=<value>. On thehive/jdbcbackends the same property is a storage-location URI. Because the name means two different things by backend, users copying a hive/jdbc example naturally set a URI likewarehouse: "s3://warehouse/"on a REST catalog.The catalog is then created without complaint (the value is accepted, never validated), and the failure is deferred to the first table/namespace operation:
The error gives no hint that the fix is to remove the property (or set it to a catalog name). The value is forwarded verbatim: the REST branch of the required-check is skipped (
IcebergCatalogWrapper.java:93), and the receiving IRC treats it as a catalog name (IcebergConfigOperations.java:128->IcebergCatalogWrapperManager.java:123).From the end-user's perspective (UX matrix)
The confusion is best seen as a matrix over two dimensions — backend (
restvshive/jdbc) and whetherwarehouseis a URI, a name, or omitted — comparing what the user intends against the outcome:warehousehive/jdbcs3://warehouse/(URI)hive/jdbcThe 'warehouse' parameter must have a value.restrestsales(a name)rests3://warehouse/(URI)200; first op →NoSuchWarehouseException: Couldn't find Iceberg configuration for catalog s3://warehouse/rest""(empty)The whole issue is one cell —
rest+ URI. It's dangerous because onhive/jdbcthat same URI value is required and correct, so the user's instinct ("warehouse = my S3 path") is right everywhere except here — and unlike the hive/jdbc mistake, this one is silently accepted at create and only fails later.Flow (what actually happens)
flowchart TD U(["User creates a lakehouse-iceberg catalog<br/>with a 'warehouse' value"]) --> B{catalog-backend?} B -->|hive / jdbc| H["'warehouse' = STORAGE LOCATION"] H --> HV{value provided?} HV -->|"s3://warehouse/ (URI)"| HOK["✅ used as the data location — matches intent"] HV -->|omitted| HERR["❌ rejected at CREATE, clear message:<br/>'The warehouse parameter must have a value'"] B -->|rest| R["Gravitino forwards the value verbatim:<br/>GET /v1/config?warehouse=VALUE"] R --> IRC["IRC interprets VALUE as a CATALOG NAME to look up"] IRC --> F{name resolves?} F -->|"omitted → default, or real name e.g. 'sales'"| ROK["✅ 200 ConfigResponse — catalog selected"] F -->|"s3://warehouse/ (URI) — no such name"| RERR["❌ 404 → NoSuchWarehouseException<br/>CREATE returned 200; surfaces only on first use"] classDef good fill:#e6ffed,stroke:#2ea043,color:#003300; classDef bad fill:#ffebe9,stroke:#cf222e,color:#330000; class HOK,ROK good; class HERR,RERR bad;The same
s3://warehouse/edge lands on green on the hive/jdbc side and red on the rest side — that mirror is the bug in one picture.Reproduction (Docker quickstart)
Environment:
apache/gravitino:latest(native API on:8090) +apache/gravitino-iceberg-rest:latest(IRC on:9001), as reported on thegravitino-irc-quickstartsetup.Tests that expose the issue
The server-side behavior is already covered — a URI
warehouseis just another unknown catalog name and returns404(which the Iceberg REST client rethrows asNoSuchWarehouseException). Adding the URI case to the existing parameterized test makes it explicit:Verified locally: the added
"s3://warehouse/"case passes (returns 404) unchanged, confirming the value is treated as a catalog name, not a location.Related: #5756 made
warehouseoptional for REST (fixed); #9810 proposes hiding it in the Web UI; PR #9811 documented the distinction. This issue covers the remaining gap — the REST-API / catalog-init path gives no runtime hint when a URI-shaped value is used.How should we improve?
Filing to surface the quirk and gather maintainer input. Some options, in ascending effort / intrusiveness:
Option A — Improve the error message only. Catch
NoSuchWarehouseExceptionon the REST path and append: "on the REST backend,warehouseselects a catalog by name; remove it or set a catalog name." Low effort, but the hint arrives late (first operation, not creation) and threads through Iceberg's exception.Option B — WARN at catalog init when
warehouseis URI-shaped. In the branch that already special-cases REST (IcebergCatalogWrapper.java:93):Non-breaking, fires at creation, correctly scoped (hive/jdbc take the other branch). Pairs with a unit test asserting construction succeeds (no throw) plus the URI case in
TestIcebergConfig.Option C — Reject a URI-shaped
warehouseat creation. Fail fast with a clear message. Best UX for the common case, butwarehouseis a server-defined opaque identifier per the Iceberg REST spec, and some non-Gravitino IRC servers legitimately use URI/ARN-shaped identifiers — a hard reject risks breaking valid federation.Option D — Hide/omit
warehousefor REST in the Web UI. Tracked separately in [Improvement] remove warehouse properties in Iceberg catalog WEB UI if the catalog backend is REST #9810; complements but doesn't cover the REST-API path.Leaning toward Option B as the smallest non-breaking change that fires early and gives the exact hint the raw error omits — while avoiding Option C's risk to the legitimate opaque-identifier case. But the intent here is to document the quirk and discuss; happy to go with whatever the maintainers prefer (including doc-only, since PR #9811 already covers part of it).
Reported by Mark Hoerth; filed on his behalf.