apache/iceberg · error · UncheckedIOException

Cannot create namespace '%s': ref '%s' is no longer valid.

Error message

Cannot create namespace '%s': ref '%s' is no longer valid.

What it means

NessieIcebergClient.createNamespace commits a namespace content object to the currently pinned Nessie reference. Before committing it fetches existing content against that reference; if the reference has been deleted (or renamed) server-side, the Nessie API raises NessieNotFoundException, which is rethrown as an UncheckedIOException stating the ref is no longer valid. The reference object held client-side is stale relative to the server state.

Source

Thrown at nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java:255

                    Conflict.ConflictType.KEY_EXISTS, Conflict.ConflictType.NAMESPACE_ABSENT));
        if (conflict.isPresent()) {
          switch (conflict.get().conflictType()) {
            case KEY_EXISTS:
              Content conflicting = withReference(api.getContent()).key(key).get().get(key);
              throw namespaceAlreadyExists(key, conflicting, e);
            case NAMESPACE_ABSENT:
              throw new NoSuchNamespaceException(
                  e,
                  "Cannot create namespace '%s': parent namespace '%s' does not exist",
                  namespace,
                  conflict.get().key());
          }
        }
        throw new RuntimeException(
            String.format("Cannot create namespace '%s': %s", namespace, e.getMessage()));
      }
    } catch (NessieNotFoundException e) {
      throw new UncheckedIOException(
          String.format(
              "Cannot create namespace '%s': ref '%s' is no longer valid.",
              namespace, getRef().getName()),
          e);
    } catch (BaseNessieClientServerException e) {
      throw new UncheckedIOException(
          String.format("Cannot create namespace '%s': %s", namespace, e.getMessage()), e);
    }
  }

  public List<Namespace> listNamespaces(Namespace namespace) throws NoSuchNamespaceException {
    try {
      String filter = "entry.contentType == 'NAMESPACE' && ";
      if (namespace.isEmpty()) {
        filter += "size(entry.keyElements) == 1";
      } else {
        org.projectnessie.model.Namespace root =
            org.projectnessie.model.Namespace.of(namespace.levels());

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the reference exists on the Nessie server (REST GET /trees or Nessie CLI 'branch list') and recreate it if deleted.
  2. Re-create the Iceberg catalog / NessieCatalog instance so it re-resolves the reference to the current HEAD hash.
  3. If the branch was intentionally recreated, point the catalog at the new branch name via the 'ref' catalog property.
  4. Use a mutable default branch and avoid deleting branches that live jobs are pinned to.

Example fix

// before
Map<String, String> conf = Map.of(
    CatalogProperties.URI, "http://nessie:19120/api/v1",
    CatalogProperties.CATALOG_IMPL, NessieCatalog.class.getName(),
    NessieUtil.NESSIE_CLIENT_AUTH, token);
// pin ref that was later deleted
conf.put("ref", "feature-x"); // feature-x no longer exists -> error
// after
List<Reference> refs = api.getAllReferences().get().getReferences();
boolean exists = refs.stream().anyMatch(r -> r.getName().equals("feature-x"));
conf.put("ref", exists ? "feature-x" : "main"); // guard before building catalog
Defensive patterns

Strategy: try-catch

Validate before calling

boolean refExists = api.getAllReferences().get().getReferences().stream()
    .anyMatch(r -> r.getName().equals(expectedRef));

Try / catch

try {
  catalog.createNamespace(ns);
} catch (UncheckedIOException e) {
  if (e.getMessage().contains("no longer valid")) {
    // recreate/re-resolve ref, rebuild catalog, retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Calling Catalog.createNamespace on a Nessie catalog whose configured branch/tag (e.g. via ref= or branch URI parameter) was deleted or recreated (hash moved) by another client between when the catalog was configured and when createNamespace ran.

Common situations: CI pipelines or another developer deleted/recreated the working branch; a Spark/Flink job pinned to a branch that was dropped; the default branch was renamed; stale catalog instance cached across long-running sessions.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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