{"record":{"id":"686a1761e531ff52","repo":"apache/hadoop","slug":"limit-is-negative","errorCode":null,"errorMessage":"Limit is negative.","messagePattern":"Limit is negative\\.","errorType":"exception","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/CachePoolInfo.java","lineNumber":222,"sourceCode":"  @Override\n  public int hashCode() {\n    return new HashCodeBuilder().\n        append(poolName).\n        append(ownerName).\n        append(groupName).\n        append(mode).\n        append(limit).\n        append(defaultReplication).\n        append(maxRelativeExpiryMs).\n        hashCode();\n  }\n\n  public static void validate(CachePoolInfo info) throws IOException {\n    if (info == null) {\n      throw new InvalidRequestException(\"CachePoolInfo is null\");\n    }\n    if ((info.getLimit() != null) && (info.getLimit() < 0)) {\n      throw new InvalidRequestException(\"Limit is negative.\");\n    }\n    if ((info.getDefaultReplication() != null)\n            && (info.getDefaultReplication() < 0)) {\n      throw new InvalidRequestException(\"Default Replication is negative\");\n    }\n\n    if (info.getMaxRelativeExpiryMs() != null) {\n      long maxRelativeExpiryMs = info.getMaxRelativeExpiryMs();\n      if (maxRelativeExpiryMs < 0l) {\n        throw new InvalidRequestException(\"Max relative expiry is negative.\");\n      }\n      if (maxRelativeExpiryMs > Expiration.MAX_RELATIVE_EXPIRY_MS) {\n        throw new InvalidRequestException(\"Max relative expiry is too big.\");\n      }\n    }\n    validateName(info.poolName);\n  }\n","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/CachePoolInfo.java#L204-L240","documentation":"Client-side validation in CachePoolInfo.validate(): a cache pool limit that is set (non-null) and negative is rejected with InvalidRequestException before/while the request reaches the NameNode. The limit is the aggregate byte cap for a cache pool; negative values have no meaning.","triggerScenarios":"addCachePool or modifyCachePool with CachePoolInfo.setLimit(-1) (or any negative long), including arithmetic that computes a limit from free space and underflows below zero.","commonSituations":"Scripts computing pool limits from cluster metrics where subtraction yields a negative number; porting code from a system where -1 meant 'unlimited'.","solutions":["Do not set a negative limit; to express 'no limit' leave the limit unset (null) or set CachePoolInfo.limitUnlimited.","Clamp computed limits: long limit = Math.max(0, computedLimit).","Validate CachePoolInfo before submitting if the value comes from external input."],"exampleFix":"// before\nCachePoolInfo info = new CachePoolInfo(\"pool\").setLimit(requestedLimit); // requestedLimit = -1\n\n// after\nCachePoolInfo info = new CachePoolInfo(\"pool\");\nif (requestedLimit != null && requestedLimit >= 0) {\n  info.setLimit(requestedLimit);\n}","handlingStrategy":"validation","validationCode":"if (info.getLimit() != null && info.getLimit() < 0) {\n  throw new IllegalArgumentException(\"limit must be >= 0, got \" + info.getLimit());\n}\ndfs.addCachePool(info);","typeGuard":null,"tryCatchPattern":"try { dfs.addCachePool(info); }\ncatch (InvalidRequestException e) { /* surface field error to caller/config */ }","preventionTips":["Centralize CachePoolInfo construction in one factory that clamps limit/replication/expiry to valid ranges.","Use null (unset) to mean 'no limit' rather than a negative sentinel.","Validate config-derived values before submitting them to the NameNode."],"tags":["hdfs","caching","validation","configuration"],"backgroundTag":"input-validation-failed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}