apache/iceberg · error · IllegalArgumentException

loadNamespaceMetadata must be at either DATABASE or SCHEMA l

Error message

loadNamespaceMetadata must be at either DATABASE or SCHEMA level; got %s from namespace %s

What it means

SnowflakeCatalog.loadNamespaceMetadata resolves the namespace to a Snowflake identifier and only supports DATABASE or SCHEMA level. ROOT-level (empty) namespaces and other scopes hit the default branch and throw IllegalArgumentException, since there is no database/schema object to check for existence.

Source

Thrown at snowflake/src/main/java/org/apache/iceberg/snowflake/SnowflakeCatalog.java:211

    }

    return results.stream().map(NamespaceHelpers::toIcebergNamespace).collect(Collectors.toList());
  }

  @Override
  public Map<String, String> loadNamespaceMetadata(Namespace namespace)
      throws NoSuchNamespaceException {
    SnowflakeIdentifier id = NamespaceHelpers.toSnowflakeIdentifier(namespace);
    boolean namespaceExists;
    switch (id.type()) {
      case DATABASE:
        namespaceExists = snowflakeClient.databaseExists(id);
        break;
      case SCHEMA:
        namespaceExists = snowflakeClient.schemaExists(id);
        break;
      default:
        throw new IllegalArgumentException(
            String.format(
                "loadNamespaceMetadata must be at either DATABASE or SCHEMA level; got %s from namespace %s",
                id, namespace));
    }
    if (namespaceExists) {
      return ImmutableMap.of();
    } else {
      throw new NoSuchNamespaceException(
          "Namespace '%s' with snowflake identifier '%s' doesn't exist", namespace, id);
    }
  }

  @Override
  public boolean dropNamespace(Namespace namespace) {
    throw new UnsupportedOperationException(
        "SnowflakeCatalog does not currently support dropNamespace");
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Call loadNamespaceMetadata only with one-level (database) or two-level (database.schema) namespaces
  2. Skip ROOT-level namespaces in generic metadata loaders
  3. Validate namespace.levels().length is 1 or 2 before calling

Example fix

// before
catalog.loadNamespaceMetadata(Namespace.empty()); // throws
// after
if (namespace.levels().length >= 1 && namespace.levels().length <= 2) {
  catalog.loadNamespaceMetadata(namespace);
}
Defensive patterns

Strategy: validation

Validate before calling

int depth = namespace.levels().length;
if (depth < 1 || depth > 2) {
  throw new IllegalArgumentException(
      "loadNamespaceMetadata requires DATABASE or SCHEMA level: " + namespace);
}

Type guard

boolean isLoadableNamespace(Namespace ns) {
  int d = ns == null ? 0 : ns.levels().length;
  return d == 1 || d == 2;
}

Try / catch

try {
  catalog.loadNamespaceMetadata(namespace);
} catch (IllegalArgumentException e) {
  // skip ROOT-level or over-deep namespaces
}

Prevention

When it happens

Trigger: Calling loadNamespaceMetrics on an empty namespace (Namespace.empty()) or a namespace with more than two levels; the namespace must be 1 or 2 levels.

Common situations: Generic code loading metadata for Namespace.empty() assuming a root entry exists; engines probing root-level namespace metadata; mixed-level loops over namespaces.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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