{"record":{"id":"f0c4e297dec7fa5b","repo":"apache/hadoop","slug":"name-cannot-be-have-a-ch-char","errorCode":null,"errorMessage":"Name cannot be have a '{ch}' char","messagePattern":"Name cannot be have a '(.+?)' char","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/MultipleOutputs.java","lineNumber":236,"sourceCode":"   * @param namedOutput named output Name\n   * @throws IllegalArgumentException if the output name is not valid.\n   */\n  private static void checkTokenName(String namedOutput) {\n    if (namedOutput == null || namedOutput.length() == 0) {\n      throw new IllegalArgumentException(\n        \"Name cannot be NULL or emtpy\");\n    }\n    for (char ch : namedOutput.toCharArray()) {\n      if ((ch >= 'A') && (ch <= 'Z')) {\n        continue;\n      }\n      if ((ch >= 'a') && (ch <= 'z')) {\n        continue;\n      }\n      if ((ch >= '0') && (ch <= '9')) {\n        continue;\n      }\n      throw new IllegalArgumentException(\n        \"Name cannot be have a '\" + ch + \"' char\");\n    }\n  }\n\n  /**\n   * Checks if output name is valid.\n   *\n   * name cannot be the name used for the default output\n   * @param outputPath base output Name\n   * @throws IllegalArgumentException if the output name is not valid.\n   */\n  private static void checkBaseOutputPath(String outputPath) {\n    if (outputPath.equals(FileOutputFormat.PART)) {\n      throw new IllegalArgumentException(\"output name cannot be 'part'\");\n    }\n  }\n  \n  /**","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/MultipleOutputs.java#L218-L254","documentation":"Thrown as IllegalArgumentException from MultipleOutputs.checkTokenName (MultipleOutputs.java:236). After the null/empty check, each character of a named output must be A-Z, a-z, or 0-9; the first character outside those ranges produces 'Name cannot be have a '<ch>' char'. Named outputs become part of config keys and file names, hence the strict token rule.","triggerScenarios":"addNamedOutput or write with names containing '-', '_', '.', '/', or spaces: 'my-output', 'out_1', 'sales.eur', 'raw data'. All fail because hyphen/underscore/dot/space are not in the allowed ranges.","commonSituations":"Porting old-API MultipleTextOutputFormat code where arbitrary file-name fragments were allowed; deriving channel names from dates ('2026-08-22') or domain strings ('user-clicks') without sanitizing.","solutions":["Use letters and digits only: 'myoutput', 'out1', 'salesEUR'","Sanitize dynamic names: strip or replace disallowed characters before calling addNamedOutput/write","Put the fancy formatting into the baseOutputPath argument of mos.write(name, k, v, baseOutputPath) instead of the channel name — paths there may contain '/'"],"exampleFix":"// before\nMultipleOutputs.addNamedOutput(job, \"user-clicks\", TextOutputFormat.class, ...);\n\n// after\nMultipleOutputs.addNamedOutput(job, \"userclicks\", TextOutputFormat.class, ...);\n// and keep the pretty name in the file path instead:\nmos.write(\"userclicks\", key, value, \"user-clicks/r-0001\");","handlingStrategy":"validation","validationCode":"// sanitize dynamic names to the allowed alphabet\nstatic String sanitizeChannel(String raw) {\n  return raw == null ? null : raw.replaceAll(\"[^A-Za-z0-9]\", \"\");\n}","typeGuard":"static boolean isValidMultipleOutputsToken(String name) {\n  if (name == null || name.isEmpty()) return false;\n  for (char ch : name.toCharArray()) {\n    if (!((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'))) return false;\n  }\n  return !name.equals(\"part\");\n}","tryCatchPattern":null,"preventionTips":["Keep channel names alphanumeric; move formatting into baseOutputPath","Sanitize date/domain-derived names","Add a driver-side unit test for every channel name used by tasks"],"tags":["hadoop","mapreduce","multiple-outputs","validation","illegalargument","naming"],"backgroundTag":"invalid-named-output-name","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}