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

  1. Recreate the missing branch/tag (e.g. from its last known hash or from 'main') and rerun the rename.
  2. Recreate the catalog against a valid reference and retry renameTable/renameView.
  3. Check whether your rename job races with branch lifecycle automation and reorder or protect the branch.
  4. 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

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


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