apache/hadoop · error · UnsupportedOperationException

Received unimplemented DNA_SHUTDOWN

Error message

Received unimplemented DNA_SHUTDOWN

What it means

The DataNode's command dispatcher has a case for DatanodeProtocol.DNA_SHUTDOWN that intentionally throws UnsupportedOperationException — as the code comment notes, the stock NameNode never sends this command (HDFS-2987) and the DN has no handler for it. Receiving it means the peer is not behaving like a stock NN.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPOfferService.java:773

        throw e;
      }
      break;
    case DatanodeProtocol.DNA_CACHE:
      LOG.info("DatanodeCommand action: DNA_CACHE for " +
        blockIdCmd.getBlockPoolId() + " of [" +
          blockIdArrayToString(blockIdCmd.getBlockIds()) + "]");
      dn.getFSDataset().cache(blockIdCmd.getBlockPoolId(), blockIdCmd.getBlockIds());
      break;
    case DatanodeProtocol.DNA_UNCACHE:
      LOG.info("DatanodeCommand action: DNA_UNCACHE for " +
        blockIdCmd.getBlockPoolId() + " of [" +
          blockIdArrayToString(blockIdCmd.getBlockIds()) + "]");
      dn.getFSDataset().uncache(blockIdCmd.getBlockPoolId(), blockIdCmd.getBlockIds());
      break;
    case DatanodeProtocol.DNA_SHUTDOWN:
      // TODO: DNA_SHUTDOWN appears to be unused - the NN never sends this command
      // See HDFS-2987.
      throw new UnsupportedOperationException("Received unimplemented DNA_SHUTDOWN");
    case DatanodeProtocol.DNA_FINALIZE:
      String bp = ((FinalizeCommand) cmd).getBlockPoolId();
      LOG.info("Got finalize command for block pool " + bp);
      assert getBlockPoolId().equals(bp) :
        "BP " + getBlockPoolId() + " received DNA_FINALIZE " +
        "for other block pool " + bp;

      dn.finalizeUpgradeForPool(bp);
      break;
    case DatanodeProtocol.DNA_RECOVERBLOCK:
      String who = "NameNode at " + nnSocketAddress;
      dn.getBlockRecoveryWorker().recoverBlocks(who,
          ((BlockRecoveryCommand)cmd).getRecoveringBlocks());
      break;
    case DatanodeProtocol.DNA_ACCESSKEYUPDATE:
      LOG.info("DatanodeCommand action from active NN {}: DNA_ACCESSKEYUPDATE", nnSocketAddress);
      if (dn.isBlockTokenEnabled) {
        dn.blockPoolTokenSecretManager.addKeys(

View on GitHub (pinned to 2add963021)

Solutions

  1. Stop sending DNA_SHUTDOWN from custom NN-side code — decommission + stopping the DN process is the supported path
  2. If this comes from a stock NN, capture the NN version and heartbeat trace and file a HADOOP JIRA; it indicates protocol corruption
Defensive patterns

Strategy: try-catch

Try / catch

// Only relevant for custom command dispatchers built on DatanodeProtocol
try {
  processCommands(cmds);
} catch (UnsupportedOperationException e) {
  if (e.getMessage() != null && e.getMessage().contains("DNA_SHUTDOWN")) {
    // peer is not a stock NN: log and refuse instead of killing the actor thread
    LOG.error("Peer sent unimplemented DNA_SHUTDOWN; ignoring command source");
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: A modified/forked NameNode, test harness, or crafted DatanodeProtocol response includes DNA_SHUTDOWN in a heartbeat reply; the DN's actor thread hits the unhandled case and dies.

Common situations: In-house NN forks reusing the ancient shutdown command; protocol fuzzing/replay tests; extremely old pre-2.x protocol semantics reused in tooling.

Related errors


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