apache/hadoop · error · LeaseException

Lease desired but no lease threads configured, set fs.azure.

Error message

Lease desired but no lease threads configured, set fs.azure.lease.threads

What it means

The AbfsLease constructor throws LeaseException("Lease desired but no lease threads configured, set fs.azure.lease.threads") when an asynchronous lease is requested (isAsync) and AbfsClient.getNumLeaseThreads() < 1. The lease scheduler pool is sized by fs.azure.lease.threads, whose default is 0 (FileSystemConfigurations.DEFAULT_LEASE_THREADS = 0), so async leasing is opt-in: it fails fast at lease creation rather than deadlocking later.

Source

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

   * @param eTag                ETag of the file
   * @param tracingContext      Tracing context
   * @throws AzureBlobFileSystemException if the lease cannot be acquired
   */
  @VisibleForTesting
  public AbfsLease(AbfsClient client, String path, final boolean isAsync, int acquireMaxRetries,
                   int acquireRetryInterval, final long leaseRefreshDuration,
                   final String eTag,
                   TracingContext tracingContext) throws AzureBlobFileSystemException {
    this.leaseFreed = false;
    this.client = client;
    this.path = path;
    this.tracingContext = tracingContext;
    this.leaseRefreshDuration = leaseRefreshDuration;
    this.leaseRefreshDurationInSeconds = (int) leaseRefreshDuration / ONE_THOUSAND;
    this.isAsync = isAsync;

    if (isAsync && client.getNumLeaseThreads() < 1) {
      throw new LeaseException(ERR_NO_LEASE_THREADS);
    }

    // Try to get the lease a specified number of times, else throw an error
    RetryPolicy retryPolicy = RetryPolicies.retryUpToMaximumCountWithFixedSleep(
        acquireMaxRetries, acquireRetryInterval, TimeUnit.SECONDS);
    this.timer = new Timer(
            String.format("lease-refresh-timer-%s", path), true);
    acquireLease(retryPolicy, 0, acquireRetryInterval, 0, eTag,
        new TracingContext(tracingContext));

    while (leaseID == null && exception == null) {
      try {
        future.get();
      } catch (Exception e) {
        LOG.debug("Got exception waiting for acquire lease future. Checking if lease ID or "
            + "exception have been set", e);
      }
    }

View on GitHub (pinned to 2add963021)

Solutions

  1. Set fs.azure.lease.threads to at least 1 (e.g., 4) wherever async leases are used
  2. If you do not need async leases, disable the lease feature rather than leaving threads at 0
  3. Verify with conf.getInt("fs.azure.lease.threads", 0) before initializing the filesystem

Example fix

<!-- before: missing / zero threads -->
<property>
  <name>fs.azure.lease.threads</name>
  <value>0</value>
</property>

<!-- after -->
<property>
  <name>fs.azure.lease.threads</name>
  <value>4</value>
</property>
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast on bad lease config before creating the filesystem
int leaseThreads = conf.getInt("fs.azure.lease.threads", 0);
if (usingAsyncLeases && leaseThreads < 1) {
  throw new IllegalArgumentException(
      "fs.azure.lease.threads must be >= 1 when async leases are used (was "
      + leaseThreads + ")");
}

Prevention

When it happens

Trigger: Code path acquiring an async lease (lease-class output streams on leased files) while fs.azure.lease.threads is unset or 0 in core-site.xml / the abfs mount config; configs copied from templates that omit lease keys; setting the value to 0 explicitly to 'disable' the pool while still using async leases.

Common situations: Enabling fs.azure lease features (fs.azure.lease.*) without sizing the thread pool; environment-specific configs (test/dev) missing keys that prod has; upgrading hadoop-azure to a version where the async-lease path became the default for leased writes.

Related errors


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