apache/iceberg · error · NoSuchNamespaceException

Cannot create table %s in catalog %s. Namespace %s does not

Error message

Cannot create table %s in catalog %s. Namespace %s does not exist

What it means

When creating a table with the JDBC catalog in strict mode (jdbc.strict-mode=true, via JdbcUtil.STRICT_MODE_PROPERTY), createTable first verifies the parent namespace exists. If not, it throws NoSuchNamespaceException instead of silently creating the table row under an unregistered namespace. In non-strict mode this check is skipped for backward compatibility.

Source

Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcTableOperations.java:169

            connections,
            catalogName,
            tableIdentifier,
            newMetadataLocation,
            oldMetadataLocation);

    if (updatedRecords == 1) {
      LOG.debug("Successfully committed to existing table: {}", tableIdentifier);
    } else {
      throw new CommitFailedException(
          "Failed to update table %s from catalog %s", tableIdentifier, catalogName);
    }
  }

  private void createTable(String newMetadataLocation) throws SQLException, InterruptedException {
    Namespace namespace = tableIdentifier.namespace();
    if (PropertyUtil.propertyAsBoolean(catalogProperties, JdbcUtil.STRICT_MODE_PROPERTY, false)
        && !JdbcUtil.namespaceExists(catalogName, connections, namespace)) {
      throw new NoSuchNamespaceException(
          "Cannot create table %s in catalog %s. Namespace %s does not exist",
          tableIdentifier, catalogName, namespace);
    }

    if (schemaVersion == JdbcUtil.SchemaVersion.V1
        && JdbcUtil.viewExists(catalogName, connections, tableIdentifier)) {
      throw new AlreadyExistsException("View with same name already exists: %s", tableIdentifier);
    }

    if (JdbcUtil.tableExists(schemaVersion, catalogName, connections, tableIdentifier)) {
      throw new AlreadyExistsException("Table already exists: %s", tableIdentifier);
    }

    int insertRecord =
        JdbcUtil.doCommitCreateTable(
            schemaVersion,
            connections,
            catalogName,

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Create the namespace first: catalog.createNamespace(namespace)
  2. Fix the namespace spelling in the table identifier
  3. Set jdbc.strict-mode=false if legacy behavior (no namespace check) is intended, though namespaces won't be validated
  4. For legacy catalogs, backfill namespace rows in jdbc_namespaces before enabling strict mode

Example fix

// before
catalog.createTable(TableIdentifier.of("prod.events", "tbl"), schema); // ns missing
// after
Namespace ns = Namespace.of("prod", "events");
if (!catalog.namespaceExists(ns)) {
  catalog.createNamespace(ns);
}
catalog.createTable(TableIdentifier.of(ns, "tbl"), schema);
Defensive patterns

Strategy: validation

Validate before calling

if (!catalog.namespaceExists(namespace)) { catalog.createNamespace(namespace); }

Try / catch

try { catalog.createTable(identifier, schema); } catch (NoSuchNamespaceException e) { catalog.createNamespace(identifier.namespace()); catalog.createTable(identifier, schema); }

Prevention

When it happens

Trigger: catalog.createTable() called with a namespace never registered via createNamespace(); typo in namespace name; namespace dropped by another client just before table creation; strict mode newly enabled while existing namespaces predate namespace registration (V0 schema).

Common situations: Migration from older JDBC catalog versions where namespaces were never stored; typos in namespace passed through engine SQL (CREATE TABLE ns.tbl ...); strict mode turned on without migrating namespace rows.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/6ec43b3a7fcd20df. Report an issue: GitHub.