apache/hadoop · error · LeaseException

There is already an existing lease operation

Error message

There is already an existing lease operation

What it means

AbfsLease.acquireLease throws LeaseException("There is already an existing lease operation") when a previous async acquisition Future is still in flight (future != null && !future.isDone()). The class enforces one outstanding acquire per lease object because the callback writes shared state (leaseID, timer task), so overlapping acquires are rejected up front.

Source

Thrown at hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsLease.java:180

  }

  /**
   * Acquire a lease on the given path.
   *
   * @param retryPolicy        Retry policy
   * @param numRetries         Number of retries
   * @param retryInterval      Retry interval in seconds
   * @param delay              Delay in seconds
   * @param eTag               ETag of the file
   * @param tracingContext     Tracing context
   * @throws LeaseException if the lease cannot be acquired
   */
  private void acquireLease(RetryPolicy retryPolicy, int numRetries,
      int retryInterval, long delay, final String eTag, TracingContext tracingContext)
      throws LeaseException {
    LOG.debug("Attempting to acquire lease on {}, retry {}", path, numRetries);
    if (future != null && !future.isDone()) {
      throw new LeaseException(ERR_LEASE_FUTURE_EXISTS);
    }
    FutureCallback<AbfsRestOperation> acquireCallback = new FutureCallback<AbfsRestOperation>() {
      @Override
      public void onSuccess(@Nullable AbfsRestOperation op) {
        leaseID = op.getResult().getResponseHeader(HttpHeaderConfigurations.X_MS_LEASE_ID);
        if (leaseRefreshDuration != INFINITE_LEASE_DURATION) {
          leaseTimerTask = new LeaseTimerTask(client, path,
                  leaseID, tracingContext);
          timer.scheduleAtFixedRate(leaseTimerTask, leaseRefreshDuration / 2,
                  leaseRefreshDuration / 2);
        }
        LOG.debug("Acquired lease {} on {}", leaseID, path);
      }

      @Override
      public void onFailure(Throwable throwable) {
        try {
          if (RetryPolicy.RetryAction.RetryDecision.RETRY

View on GitHub (pinned to 2add963021)

Solutions

  1. Wait for the in-flight acquisition to finish before retrying (poll the lease state / synchronize on the lease object)
  2. Free the existing lease first, then acquire again, so future is done and state is clean
  3. Serialize all lease operations per path through a single owner/thread
  4. Catch LeaseException and back off instead of retrying immediately

Example fix

// before
try {
  lease.acquire(...);          // may overlap a still-running acquire
} catch (LeaseException e) {
  lease.acquire(...);          // LeaseException: existing lease operation
}

// after
synchronized (lease) {
  while (!lease.isFree()) {    // wait for prior future to complete
    lease.wait(100);
  }
  lease.acquire(...);
}
Defensive patterns

Strategy: retry

Validate before calling

// Serialize lease acquisition per path; never overlap acquires
synchronized (leaseLock) {
  while (acquireInFlight) {
    try { leaseLock.wait(100); } catch (InterruptedException ie) {
      Thread.currentThread().interrupt(); return;
    }
  }
  acquireInFlight = true;
}
try { lease.acquire(...); } finally {
  synchronized (leaseLock) { acquireInFlight = false; leaseLock.notifyAll(); }
}

Try / catch

try {
  lease.acquire(...);
} catch (LeaseException e) {
  if (e.getMessage().contains("already an existing lease operation")) {
    Thread.sleep(backoffMs);      // let the in-flight future finish
    lease.acquire(...);           // then retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Triggering acquireLease twice on the same AbfsLease before the first async acquire completes — e.g., a retry loop that immediately re-invokes on timeout, or two threads racing to (re)acquire the lease on the same path/lease handle.

Common situations: Hand-rolled retry logic around lease acquisition; concurrent writers each trying to acquire the lease object; recovery code that re-acquires after failure without waiting for the prior attempt's future to finish.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/890b77d176c213d6. Report an issue: GitHub.