apache/iceberg · error · org.apache.spark.sql.catalyst.analysis.NamespaceAlreadyExistsException

NamespaceAlreadyExistsException

Error message

NamespaceAlreadyExistsException: <namespace>

What it means

createNamespace delegates to the SupportsNamespaces catalog; if the underlying catalog reports AlreadyExistsException, SparkCatalog translates it to Spark's NamespaceAlreadyExistsException. Namespace creation is not idempotent unless the catalog implements createOrExists semantics.

Solutions

  1. Use CREATE NAMESPACE IF NOT EXISTS
  2. Check namespaceExists(namespace) before creating
  3. Catch NamespaceAlreadyExistsException and treat it as success in idempotent pipelines
  4. Remove the conflicting namespace only if it is safe

Example fix

// before
spark.sql("CREATE NAMESPACE prod.db");
// after
spark.sql("CREATE NAMESPACE IF NOT EXISTS prod.db");
Defensive patterns

Strategy: try-catch

Validate before calling

if (!spark.catalog().namespaceExists("prod.db")) { spark.sql("CREATE NAMESPACE prod.db"); }

Try / catch

try { spark.sql("CREATE NAMESPACE prod.db"); } catch (NamespaceAlreadyExistsException e) { /* treat as success */ }

Prevention

When it happens

Trigger: CREATE NAMESPACE without IF NOT EXISTS when the namespace already exists; concurrent creation from two jobs; retrying a failed job that already created the namespace.

Common situations: Multi-tenant setups where another team created the namespace; pipeline retries; HadoopCatalog backed by an existing directory with metadata files.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:491

    throw new NoSuchNamespaceException(namespace);
  }

  @Override
  public void createNamespace(String[] namespace, Map<String, String> metadata)
      throws NamespaceAlreadyExistsException {
    if (asNamespaceCatalog != null) {
      try {
        if (asNamespaceCatalog instanceof HadoopCatalog
            && DEFAULT_NS_KEYS.equals(metadata.keySet())) {
          // Hadoop catalog will reject metadata properties, but Spark automatically adds "owner".
          // If only the automatic properties are present, replace metadata with an empty map.
          asNamespaceCatalog.createNamespace(Namespace.of(namespace), ImmutableMap.of());
        } else {
          asNamespaceCatalog.createNamespace(Namespace.of(namespace), metadata);
        }
      } catch (AlreadyExistsException e) {
        throw new NamespaceAlreadyExistsException(namespace);
      }
    } else {
      throw new UnsupportedOperationException(
          "Namespaces are not supported by catalog: " + catalogName);
    }
  }

  @Override
  public void alterNamespace(String[] namespace, NamespaceChange... changes)
      throws NoSuchNamespaceException {
    if (asNamespaceCatalog != null) {
      Map<String, String> updates = Maps.newHashMap();
      Set<String> removals = Sets.newHashSet();
      for (NamespaceChange change : changes) {
        if (change instanceof NamespaceChange.SetProperty) {
          NamespaceChange.SetProperty set = (NamespaceChange.SetProperty) change;
          updates.put(set.property(), set.value());
        } else if (change instanceof NamespaceChange.RemoveProperty) {

View on GitHub (pinned to 86d9c8fc54)