apache/hadoop · error · InvalidRequestException

Max relative expiry is negative.

Error message

Max relative expiry is negative.

What it means

CachePoolInfo.validate() throws when a pool's maxRelativeExpiryMs is set and negative. Max relative expiry bounds how far in the future directives in the pool may set their expiration; a negative duration is meaningless.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/CachePoolInfo.java:232

        hashCode();
  }

  public static void validate(CachePoolInfo info) throws IOException {
    if (info == null) {
      throw new InvalidRequestException("CachePoolInfo is null");
    }
    if ((info.getLimit() != null) && (info.getLimit() < 0)) {
      throw new InvalidRequestException("Limit is negative.");
    }
    if ((info.getDefaultReplication() != null)
            && (info.getDefaultReplication() < 0)) {
      throw new InvalidRequestException("Default Replication is negative");
    }

    if (info.getMaxRelativeExpiryMs() != null) {
      long maxRelativeExpiryMs = info.getMaxRelativeExpiryMs();
      if (maxRelativeExpiryMs < 0l) {
        throw new InvalidRequestException("Max relative expiry is negative.");
      }
      if (maxRelativeExpiryMs > Expiration.MAX_RELATIVE_EXPIRY_MS) {
        throw new InvalidRequestException("Max relative expiry is too big.");
      }
    }
    validateName(info.poolName);
  }

  public static void validateName(String poolName) throws IOException {
    if (poolName == null || poolName.isEmpty()) {
      // Empty pool names are not allowed because they would be highly
      // confusing.  They would also break the ability to list all pools
      // by starting with prevKey = ""
      throw new IOException("invalid empty cache pool name");
    }
  }
}

View on GitHub (pinned to 2add963021)

Solutions

  1. Use a non-negative duration; use Expiration.MAX_RELATIVE_EXPIRY_MS for 'never expire'.
  2. Clamp computed expiries: long expiry = Math.max(0L, computedExpiryMs);
  3. Validate units (ms, not s) before calling setMaxRelativeExpiryMs.

Example fix

// before
info.setMaxRelativeExpiryMs(endTimeMs - System.currentTimeMillis()); // can be negative

// after
long rel = Math.max(0L, endTimeMs - System.currentTimeMillis());
info.setMaxRelativeExpiryMs(rel);
Defensive patterns

Strategy: validation

Validate before calling

long maxExpiry = Math.max(0L, requestedExpiryMs);
info.setMaxRelativeExpiryMs(maxExpiry);

Try / catch

try { dfs.addCachePool(info); }
catch (InvalidRequestException e) { /* reject the expiry input at the API boundary */ }

Prevention

When it happens

Trigger: addCachePool/modifyCachePool with setMaxRelativeExpiryMs(negative), e.g. computing 'now - lastExpiry' style values or unit conversion mistakes (passing a negative millisecond delta).

Common situations: Time arithmetic with System.currentTimeMillis() differences that can go negative, or passing seconds where milliseconds are expected via a negative sentinel.

Related errors


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