{"record":{"id":"6e8c8d855829a704","repo":"apache/hadoop","slug":"cannot-initialize-expiryperiod-to-when-cache-is","errorCode":null,"errorMessage":"Cannot initialize expiryPeriod to {} when cache is enabled.","messagePattern":"Cannot initialize expiryPeriod to (.+?) when cache is enabled\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/PeerCache.java","lineNumber":105,"sourceCode":"      return time;\n    }\n  }\n\n  private Daemon daemon;\n  /** A map for per user per datanode. */\n  private final LinkedListMultimap<Key, Value> multimap =\n      LinkedListMultimap.create();\n  private final int capacity;\n  private final long expiryPeriod;\n\n  public PeerCache(int c, long e) {\n    this.capacity = c;\n    this.expiryPeriod = e;\n\n    if (capacity == 0 ) {\n      LOG.debug(\"SocketCache disabled.\");\n    } else if (expiryPeriod == 0) {\n      throw new IllegalStateException(\"Cannot initialize expiryPeriod to \" +\n         expiryPeriod + \" when cache is enabled.\");\n    }\n  }\n\n  private boolean isDaemonStarted() {\n    return daemon != null;\n  }\n\n  private synchronized void startExpiryDaemon() {\n    // start daemon only if not already started\n    if (isDaemonStarted()) {\n      return;\n    }\n\n    daemon = new Daemon(new Runnable() {\n      @Override\n      public void run() {\n        try {","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/PeerCache.java#L87-L123","documentation":"PeerCache (DFSClient's DataNode socket cache) is constructed from dfs.client.socket.cache.capacity and dfs.client.socket.cache.expiryMs; the constructor allows either cache disabled (capacity 0) or enabled with a positive expiry. If capacity is non-zero (enabled) but expiryPeriod is 0, the expiry daemon could never expire peers, so it throws IllegalStateException at construction — which happens inside ClientContext the first time a DFSClient/ClientContext is created.","triggerScenarios":"Client configuration sets dfs.client.socket.cache.capacity > 0 together with dfs.client.socket.cache.expiryMs = 0; defaults are capacity 16 and expiry 3000ms, so this requires explicit override (or a config system that zero-fills unset numeric keys).","commonSituations":"Performance tuning gone wrong: teams disable expiry by setting expiryMs=0 while leaving capacity on; config generators that emit 0 for 'not set' numeric values; copying configs between systems with different semantics for 0.","solutions":["Set dfs.client.socket.cache.expiryMs to a positive value (default 3000)","Or disable the cache entirely: dfs.client.socket.cache.capacity=0 (expiry is then ignored)"],"exampleFix":"<!-- before: cache enabled with zero expiry -> IllegalStateException -->\n<property><name>dfs.client.socket.cache.capacity</name><value>16</value></property>\n<property><name>dfs.client.socket.cache.expiryMs</name><value>0</value></property>\n\n<!-- after -->\n<property><name>dfs.client.socket.cache.capacity</name><value>16</value></property>\n<property><name>dfs.client.socket.cache.expiryMs</name><value>3000</value></property>","handlingStrategy":"validation","validationCode":"// Validate socket cache settings before creating DFSClient contexts:\nint cap = conf.getInt(\"dfs.client.socket.cache.capacity\", 16);\nlong expiry = conf.getLong(\"dfs.client.socket.cache.expiryMs\", 3000);\nif (cap != 0 && expiry == 0) {\n  throw new IllegalArgumentException(\n      \"dfs.client.socket.cache.expiryMs must be > 0 when capacity > 0\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  FileSystem.get(hdfsUri, conf);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"Cannot initialize expiryPeriod\")) {\n    conf.setLong(\"dfs.client.socket.cache.expiryMs\", 3000);\n    FileSystem.get(hdfsUri, conf); // retry with corrected config\n  } else throw e;\n}","preventionTips":["Never set dfs.client.socket.cache.expiryMs=0 while capacity is positive — use capacity=0 to disable the cache","Add config sanity checks for paired numeric settings in deployment validators","Prefer omitting these keys to accept defaults (capacity 16, expiry 3000ms)"],"tags":["hdfs","configuration","socket-cache","dfsclient","invalid-config"],"backgroundTag":"invalid-config-combination","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}