{"record":{"id":"6c281b0945752d46","repo":"apache/hadoop","slug":"invalid-parameter-value-destination-str-is","errorCode":null,"errorMessage":"Invalid parameter value: destination = \"{str}\" is not an absolute path.","messagePattern":"Invalid parameter value: destination = \"(.+?)\" is not an absolute path\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/web/resources/DestinationParam.java","lineNumber":36,"sourceCode":"package org.apache.hadoop.hdfs.web.resources;\n\nimport org.apache.hadoop.fs.Path;\n\n/** Destination path parameter. */\npublic class DestinationParam extends StringParam {\n  /** Parameter name. */\n  public static final String NAME = \"destination\";\n  /** Default parameter value. */\n  public static final String DEFAULT = \"\";\n\n  private static final Domain DOMAIN = new Domain(NAME, null);\n\n  private static String validate(final String str) {\n    if (str == null || str.equals(DEFAULT)) {\n      return null;\n    }\n    if (!str.startsWith(Path.SEPARATOR)) {\n      throw new IllegalArgumentException(\"Invalid parameter value: \" + NAME\n          + \" = \\\"\" + str + \"\\\" is not an absolute path.\");\n    }\n    return new Path(str).toUri().getPath();\n  }\n\n  /**\n   * Constructor.\n   * @param str a string representation of the parameter value.\n   */\n  public DestinationParam(final String str) {\n    super(DOMAIN, validate(str));\n  }\n\n  @Override\n  public String getName() {\n    return NAME;\n  }\n}","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/web/resources/DestinationParam.java#L18-L54","documentation":"DestinationParam validates the 'destination' query parameter carried by WebHDFS RENAME (and symlink-style) PUT requests. The validate() method at DestinationParam.java:30-43 treats null or \"\" as absent, but any non-empty value that does not start with Path.SEPARATOR ('/') is rejected with this IllegalArgumentException (HTTP 400). The value is then normalized via new Path(str).toUri().getPath(), so the library insists on fully-qualified absolute HDFS paths.","triggerScenarios":"PUT ?op=RENAME&destination=dir2/newname (relative path, no leading '/'); destination built from a bare filename such as destination=file2.txt; destination containing a URL-encoded relative path after decode; sending destination= (empty is OK, it becomes null) but destination=. or destination=.. fails.","commonSituations":"Building the destination from Path.getFileName() or a relative Path.toString() instead of the full path; scripts that join path segments without a leading separator; porting code from a FileSystem.rename(src, dst) call where dst was relative to the working directory (WebHDFS has no working-directory context for the parameter).","solutions":["Prefix the destination with '/' so it is absolute from the HDFS root, e.g. destination=/dir2/newname.","Build the parameter from a qualified Path: path.makeQualified(fs.getUri(), fs.getWorkingDirectory()).toUri().getPath().","Use FileSystem.rename() via the webhdfs:// client, which constructs DestinationParam for you.","URL-encode the destination after making it absolute (spaces, '%', etc.)."],"exampleFix":"// before\nString dest = newPathName;                 // e.g. \"dir2/newname\"\nString url = base + \"?op=RENAME&destination=\" + dest;\n// after\nString dest = \"/\" + rootDir + \"/\" + newPathName;  // \"/data/dir2/newname\"\nString url = base + \"?op=RENAME&destination=\" + URLEncoder.encode(dest, \"UTF-8\");","handlingStrategy":"validation","validationCode":"static String checkedDestination(String root, String dest) {\n  Path p = new Path(root, dest).makeQualified(new Path(root).toUri(), new Path(\"/\"));\n  String abs = p.toUri().getPath();\n  if (!abs.startsWith(\"/\")) throw new IllegalArgumentException(\"destination must be absolute: \" + abs);\n  return abs;\n}","typeGuard":"static boolean isAbsoluteHdfsPath(String s) { return s != null && !s.isEmpty() && s.startsWith(\"/\"); }","tryCatchPattern":"try {\n  fs.rename(src, new Path(root, name));   // webhdfs client builds DestinationParam\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"is not an absolute path\")) {\n    // recompute destination as absolute and retry once\n  }\n}","preventionTips":["Never pass Path.getFileName() output as 'destination'; always qualify against the parent/root first.","Keep a helper that joins root + relative and asserts the leading '/'.","URL-encode the destination after validation."],"tags":["webhdfs","rename","path-validation","query-param","hdfs"],"backgroundTag":"invalid-path-parameter","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}