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
- Verify the reference exists on the Nessie server (REST GET /trees or Nessie CLI 'branch list') and recreate it if deleted.
- Re-create the Iceberg catalog / NessieCatalog instance so it re-resolves the reference to the current HEAD hash.
- If the branch was intentionally recreated, point the catalog at the new branch name via the 'ref' catalog property.
- 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
- Do not delete/recreate branches that long-running jobs are pinned to.
- Resolve the ref fresh (rebuild catalog) instead of caching catalog instances across branch mutations.
- Monitor Nessie branch lifecycle in CI to avoid racing running jobs.
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
- Cannot list top-level namespaces: ref '%s' is no longer vali
- Cannot list child namespaces from '%s': ref '%s' is no longe
- Unable to list %ss due to missing ref '%s'
- Cannot create namespace '%s': parent namespace '%s' does not
- Cannot create namespace '%s': %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/84d526b7caf31826.
Report an issue: GitHub.