apache/hadoop · error · IOException

Illegal parameters to TransferFsImage

Error message

Illegal parameters to TransferFsImage

What it means

GetImageParams, the GET-side parameter parser of ImageServlet, requires that exactly one transfer operation is selected: the counters isGetImage, isGetEdit and isGetAliasMap must total exactly one. Requesting two things at once (numGets > 1) or none at all (numGets == 0) is rejected as an illegal TransferFsImage request before any data is served.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ImageServlet.java:453

          }
        } else if (key.equals("getedit")) { 
          isGetEdit = true;
          startTxId = ServletUtil.parseLongParam(request, START_TXID_PARAM);
          endTxId = ServletUtil.parseLongParam(request, END_TXID_PARAM);
        } else if (key.equals(STORAGEINFO_PARAM)) {
          storageInfoString = val[0];
        } else if (key.equals("getaliasmap")) {
          isGetAliasMap = true;
          String bootstrapStandby = ServletUtil.getParameter(request,
              IS_BOOTSTRAP_STANDBY);
          isBootstrapStandby = bootstrapStandby != null &&
              Boolean.parseBoolean(bootstrapStandby);
        }
      }

      int numGets = (isGetImage?1:0) + (isGetEdit?1:0) + (isGetAliasMap?1:0);
      if ((numGets > 1) || (numGets == 0)) {
        throw new IOException("Illegal parameters to TransferFsImage");
      }
    }

    public String getStorageInfoString() {
      return storageInfoString;
    }

    public long getTxId() {
      Preconditions.checkState(isGetImage);
      return txId;
    }

    public NameNodeFile getNameNodeFile() {
      Preconditions.checkState(isGetImage);
      return nnf;
    }

    public long getStartTxId() {

View on GitHub (pinned to 2add963021)

Solutions

  1. Send exactly one lowercase operation parameter: getimage, getedit or getaliasmap, plus the required txid/storageinfo parameters.
  2. Instead of hand-building the URL, reuse the URL construction in TransferFsImage (it composes the exact parameter set the servlet expects).
  3. If a genuine Secondary or Standby produced the request, check for Hadoop version mixing between the NN and the peer.
Defensive patterns

Strategy: validation

Validate before calling

// Compose the query with exactly one operation before calling the servlet
static URI buildTransferUrl(String host, int port, String op, long txid, String storageInfo) {
  Set<String> allowed = new HashSet<>(Arrays.asList("getimage", "getedit", "getaliasmap"));
  if (!allowed.contains(op)) {
    throw new IllegalArgumentException("op must be one of " + allowed + ": " + op);
  }
  return URI.create(String.format("http://%s:%d/imagetransfer?%s=1&txid=%d&storageInfo=%s",
      host, port, op, txid, storageInfo));
}

Type guard

// narrows a raw query string to a valid single-op request
static boolean isSingleOpRequest(String query) {
  if (query == null) return false;
  long n = 0;
  for (String p : Arrays.asList("getimage", "getedit", "getaliasmap")) {
    if (query.matches("(^|&)(?i)" + p + "(=[^&]*)?($|&)")) n++;
  }
  return n == 1;
}

Try / catch

try {
  getImage(params);
} catch (IOException e) {
  if ("Illegal parameters to TransferFsImage".equals(e.getMessage())) {
    throw new IllegalArgumentException("Bad transfer query - exactly one of getimage/getedit/getaliasmap required", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: GET /imagetransfer with both getimage=1 and getedit=1, with neither operation parameter, or with misspelled parameter names (getImage vs getimage) - typically from hand-written scripts or curl rather than the real Secondary, whose client code always sends exactly one op.

Common situations: Custom monitoring or backup tooling hitting the servlet directly; version assumptions about the parameter contract; typo'd query keys; modified 2NN deployments.

Related errors


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