{"record":{"id":"676cdd82c587a548","repo":"apache/hadoop","slug":"unexpected-urisyntaxexception","errorCode":null,"errorMessage":"unexpected URISyntaxException","messagePattern":"unexpected URISyntaxException","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/CommandWithDestination.java","lineNumber":192,"sourceCode":"  }\n\n  /**\n   *  The last arg is expected to be a local path, if only one argument is\n   *  given then the destination will be the current directory \n   *  @param args is the list of arguments\n   * @throws IOException raised on errors performing I/O.\n   */\n  protected void getLocalDestination(LinkedList<String> args)\n  throws IOException {\n    String pathString = (args.size() < 2) ? Path.CUR_DIR : args.removeLast();\n    try {\n      dst = new PathData(new URI(pathString), getConf());\n    } catch (URISyntaxException e) {\n      if (Path.WINDOWS) {\n        // Unlike URI, PathData knows how to parse Windows drive-letter paths.\n        dst = new PathData(pathString, getConf());\n      } else {\n        throw new IOException(\"unexpected URISyntaxException\", e);\n      }\n    }\n  }\n\n  /**\n   *  The last arg is expected to be a remote path, if only one argument is\n   *  given then the destination will be the remote user's directory \n   *  @param args is the list of arguments\n   *  @throws PathIOException if path doesn't exist or matches too many times \n   */\n  protected void getRemoteDestination(LinkedList<String> args)\n  throws IOException {\n    if (args.size() < 2) {\n      dst = new PathData(Path.CUR_DIR, getConf());\n    } else {\n      String pathString = args.removeLast();\n      // if the path is a glob, then it must match one and only one path\n      PathData[] items = PathData.expandAsGlob(pathString, getConf());","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/CommandWithDestination.java#L174-L210","documentation":"getLocalDestination() (used by -get/-copyToLocal, and other commands whose destination is local) wraps the last argument in java.net.URI. If the string violates RFC 2396 syntax, URISyntaxException is caught; on Windows the code falls back to PathData parsing to support drive-letter paths, but on Linux/MacOS it is rethrown as IOException('unexpected URISyntaxException'). So the local destination contains characters java.net.URI cannot parse: a Windows drive-letter path on a non-Windows host, spaces, or other URI-illegal characters.","triggerScenarios":"'hdfs dfs -get /data/file C:\\tmp\\out' executed on Linux (the C: drive-letter form only parses on Windows); a local destination containing a space like './my file.txt'; brackets, pipes, or other reserved characters in the local path.","commonSituations":"Runbooks written on Windows executed verbatim on Linux gateways; localization where paths contain spaces; automation copying the HDFS side of the command but hand-typing a local target with illegal characters.","solutions":["On Linux/MacOS use a plain POSIX destination path (e.g. /tmp/out) instead of a Windows drive-letter path","Remove URI-illegal characters (spaces, backslashes, reserved symbols) from the local destination name","Verify the destination parses first with new URI(destString) or use a destination directory that already exists and keep the generated filename simple"],"exampleFix":"# before (on Linux)\nhdfs dfs -get /data/part-00000 C:\\tmp\\part-00000\n# after\nhdfs dfs -get /data/part-00000 /tmp/part-00000","handlingStrategy":"try-catch","validationCode":"// pre-validate a local destination string the same way the shell will\ntry {\n  new java.net.URI(dest);\n} catch (java.net.URISyntaxException e) {\n  if (!org.apache.hadoop.fs.Path.WINDOWS) {\n    throw new IllegalArgumentException(\"Local destination is not URI-safe on this OS: \" + dest, e);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  shellRun(\"-get\", src, localDest);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"unexpected URISyntaxException\")) {\n    // local destination had URI-illegal chars (e.g. Windows drive path on Linux); sanitize and retry once\n    shellRun(\"-get\", src, sanitize(localDest));\n  } else throw e;\n}","preventionTips":["Use plain POSIX destination paths on Linux/MacOS; drive-letter paths only parse on Windows hosts","Keep local destination filenames free of spaces and URI-reserved characters","Centralize destination construction in one helper that runs the URI pre-check above"],"tags":["hadoop","hdfs","uri","path-parsing","local-filesystem","java"],"backgroundTag":"uri-syntax-exception","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}