apache/hadoop · error · UnsupportedOperationException

This feature is disabled. Please refer to dfs.client.block.

Error message

This feature is disabled.  Please refer to dfs.client.block.write.replace-datanode-on-failure.enable configuration property.

What it means

Thrown by the HDFS client write pipeline when it needs to add a replacement datanode (a pipeline member was lost and the remaining replicas would fall below the minimum) but datanode replacement is switched off. dfs.client.block.write.replace-datanode-on-failure.enable=false maps to Policy.DISABLE, and checkEnabled() aborts the write instead of continuing with an under-replicated pipeline.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/datatransfer/ReplaceDatanodeOnFailure.java:107

  private interface Condition {

    /** Is the condition satisfied? */
    boolean satisfy(short replication, DatanodeInfo[] existings, int nExistings,
                    boolean isAppend, boolean isHflushed);
  }

  private final Policy policy;
  private final boolean bestEffort;

  public ReplaceDatanodeOnFailure(Policy policy, boolean bestEffort) {
    this.policy = policy;
    this.bestEffort = bestEffort;
  }

  /** Check if the feature is enabled. */
  public void checkEnabled() {
    if (policy == Policy.DISABLE) {
      throw new UnsupportedOperationException(
          "This feature is disabled.  Please refer to "
          + HdfsClientConfigKeys.BlockWrite.ReplaceDatanodeOnFailure.ENABLE_KEY
          + " configuration property.");
    }
  }

  /**
   * Best effort means that the client will try to replace the failed datanode
   * (provided that the policy is satisfied), however, it will continue the
   * write operation in case that the datanode replacement also fails.
   *
   * @return Suppose the datanode replacement fails.
   *     false: An exception should be thrown so that the write will fail.
   *     true : The write should be resumed with the remaining datandoes.
   */
  public boolean isBestEffort() {
    return bestEffort;
  }

View on GitHub (pinned to 2add963021)

Solutions

  1. Set dfs.client.block.write.replace-datanode-on-failure.enable=true (or remove the property) in the client's hdfs-client.xml/core-site.xml so a replacement datanode can be added
  2. On single-node clusters keep enable=false but set dfs.client.block.write.replace-datanode-on-failure.policy=NEVER so the replacement condition is never satisfied and checkEnabled() is never reached
  3. Ensure the cluster has spare datanodes so a replacement actually exists when the policy fires
  4. Retry the failed write after the config change; the setting is read from each client Configuration instance

Example fix

// before (hdfs-client.xml)
<property>
  <name>dfs.client.block.write.replace-datanode-on-failure.enable</name>
  <value>false</value>
</property>
<property>
  <name>dfs.client.block.write.replace-datanode-on-failure.policy</name>
  <value>DEFAULT</value>
</property>

// after (single-node cluster)
<property>
  <name>dfs.client.block.write.replace-datanode-on-failure.enable</name>
  <value>false</value>
</property>
<property>
  <name>dfs.client.block.write.replace-datanode-on-failure.policy</name>
  <value>NEVER</value>
</property>

// after (multi-node cluster)
<property>
  <name>dfs.client.block.write.replace-datanode-on-failure.enable</name>
  <value>true</value>
</property>
Defensive patterns

Strategy: validation

Validate before calling

Configuration conf = new Configuration();
try {
  ReplaceDatanodeOnFailure.get(conf).checkEnabled();
} catch (UnsupportedOperationException e) {
  throw new IllegalStateException(
      "Writes will fail on datanode loss: set "
      + "dfs.client.block.write.replace-datanode-on-failure.enable=true "
      + "or policy=NEVER", e);
}

Try / catch

catch (UnsupportedOperationException e) when thrown from DFSOutputStream.write/hflush/append: report the replace-datanode-on-failure config to the operator instead of retrying the write blindly.

Prevention

When it happens

Trigger: During write/append/hflush a datanode in the pipeline dies, the policy condition is satisfied (e.g. DEFAULT condition: replication would drop below minReplication), and ReplaceDatanodeOnFailure.get(conf).checkEnabled() is invoked with policy == DISABLE because the enable property is false.

Common situations: Single-node or pseudo-distributed test clusters where the feature was disabled per old guidance ('set enable=false on small clusters') without also setting policy=NEVER; inherited production configs; appends after a datanode restart on tiny clusters.

Related errors


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