apache/iceberg · error · UncheckedIOException
Cannot rename %s '%s' to '%s': ref '%s' no longer exists.
Error message
Cannot rename %s '%s' to '%s': ref '%s' no longer exists.
What it means
renameContent (backing renameTable/renameView) commits a Delete+Put pair; if the commit fails with NessieNotFoundException, the client explains that the exception refers to the reference, not the content: the ref '%s' no longer exists. The rename is aborted with an UncheckedIOException.
Source
Thrown at nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java:483
IcebergContent existingToContent = fetchContent(to);
validateToContentForRename(from, to, existingToContent);
String contentType = NessieUtil.contentTypeString(type).toLowerCase(Locale.ROOT);
try {
commitRetry(
String.format("Iceberg rename %s from '%s' to '%s'", contentType, from, to),
Operation.Delete.of(NessieUtil.toKey(from)),
Operation.Put.of(NessieUtil.toKey(to), existingFromContent));
} catch (NessieNotFoundException e) {
// important note: the NotFoundException refers to the ref only. If a table was not found it
// would imply that the
// another commit has deleted the table from underneath us. This would arise as a Conflict
// exception as opposed to
// a not found exception. This is analogous to a merge conflict in git when a table has been
// changed by one user
// and removed by another.
throw new UncheckedIOException(
String.format(
"Cannot rename %s '%s' to '%s': ref '%s' no longer exists.",
contentType, from, to, getRef().getName()),
e);
} catch (BaseNessieClientServerException e) {
CommitFailedException commitFailedException =
new CommitFailedException(
e,
"Cannot rename %s '%s' to '%s': the current reference is not up to date.",
contentType,
from,
to);
Optional<RuntimeException> exception = Optional.empty();
if (e instanceof NessieConflictException) {
exception = NessieUtil.handleExceptionsForCommits(e, getRef().getName(), type);
}
throw exception.orElse(commitFailedException);
} catch (HttpClientException ex) {View on GitHub (pinned to 86d9c8fc54)
Solutions
- Recreate the missing branch/tag (e.g. from its last known hash or from 'main') and rerun the rename.
- Recreate the catalog against a valid reference and retry renameTable/renameView.
- Check whether your rename job races with branch lifecycle automation and reorder or protect the branch.
- Validate ref existence before starting the rename workflow (getAllReferences pre-flight).
Example fix
// before
nessieApi.deleteBranch().branchName("etl").delete(); // job on 'etl' still renaming
catalog.renameTable(t1, t2); // fails: ref 'etl' no longer exists
// after
// wait for jobs to finish / reassign them to 'main' before deleting branches
nessieApi.deleteBranch().branchName("etl").delete(); Defensive patterns
Strategy: try-catch
Validate before calling
boolean refOk = nessieApi.getAllReferences().get().getReferences()
.stream().anyMatch(r -> r.getName().equals(catalogRef));
if (!refOk) { throw new AbortException("ref " + catalogRef + " missing; skip rename"); } Try / catch
try {
catalog.renameTable(from, to);
} catch (UncheckedIOException e) {
if (String.valueOf(e.getMessage()).contains("no longer exists")) {
recreateRefThen(() -> catalog.renameTable(from, to));
} else throw e;
} Prevention
- Sequence branch deletion after dependent rename/migration jobs complete.
- Pre-flight ref existence check before rename workflows.
- Never delete-and-recreate a branch while jobs hold a catalog on it; use new branch names.
- Track branch lifecycle with webhooks to pause workloads before deletion.
When it happens
Trigger: Calling catalog.renameTable(from, to) or renameView while the catalog's configured branch/tag is deleted server-side; commitRetry's commit call receives NessieNotFoundException for the missing ref.
Common situations: CI pipelines deleting ephemeral branches while a rename job is still running; someone force-deleted/recreated the branch; catalog cached a ref name that was later renamed; misconfigured ref name that only appears valid due to earlier cached reads.
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 load namespace '%s': ref '%s' is no longer valid.
- Cannot update properties on namespace '%s': %s
- Cannot update properties on namespace '%s': ref '%s' is no l
- Cannot rename %s to %s. View already exists
- Cannot rename %s to %s. Table already exists
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/02b876aa2c9daa87.
Report an issue: GitHub.