{"record":{"id":"1a061fab0ad94c22","repo":"apache/hadoop","slug":"expected","errorCode":null,"errorMessage":"Expected ','","messagePattern":"Expected ','","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/join/Parser.java","lineNumber":440,"sourceCode":"        throw (IOException)new IOException().initCause(e);\n      }\n      for (int i = 0; i < capacity; ++i) {\n        ret.add(kids.get(i).getRecordReader(spl.get(i), job, reporter));\n      }\n      return (ComposableRecordReader)ret;\n    }\n\n    /**\n     * Parse a list of comma-separated nodes.\n     */\n    public void parse(List<Token> args, JobConf job) throws IOException {\n      ListIterator<Token> i = args.listIterator();\n      while (i.hasNext()) {\n        Token t = i.next();\n        t.getNode().setID(i.previousIndex() >> 1);\n        kids.add(t.getNode());\n        if (i.hasNext() && !TType.COMMA.equals(i.next().getType())) {\n          throw new IOException(\"Expected ','\");\n        }\n      }\n    }\n\n    public String toString() {\n      StringBuilder sb = new StringBuilder();\n      sb.append(ident + \"(\");\n      for (Node n : kids) {\n        sb.append(n.toString() + \",\");\n      }\n      sb.setCharAt(sb.length() - 1, ')');\n      return sb.toString();\n    }\n  }\n\n  private static Token reduce(Stack<Token> st, JobConf job) throws IOException {\n    LinkedList<Token> args = new LinkedList<Token>();\n    while (!st.isEmpty() && !TType.LPAREN.equals(st.peek().getType())) {","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/join/Parser.java#L422-L458","documentation":"CNode.parse walks the comma-separated argument list of a composite operator; after each node argument the next token must be TType.COMMA. A missing or wrong separator between two function arguments throws IOException(\"Expected ','\") — the canonical case is inner(tbl(\"a\") tbl(\"b\")), where the two tbl nodes reach CNode.parse as adjacent NodeTokens without a comma between them.","triggerScenarios":"Omitting the comma between two tbl(...) nodes; separating arguments with whitespace, ';', or '&'; hand-edited expressions where a ',' was dropped during refactoring.","commonSituations":"String-concatenated expressions where the comma append was forgotten; merging two expressions into one operator's argument list by hand.","solutions":["Put a comma between every pair of arguments","Build the expression with CompositeInputFormat.compose(op, fmt, paths...), which inserts commas itself","Dry-run setFormat(job) client-side to catch separator mistakes before submission"],"exampleFix":"// before\njob.set(\"mapred.join.expr\", \"inner(tbl(F,/a) tbl(F,/b))\");\n\n// after\njob.set(\"mapred.join.expr\", \"inner(tbl(F,/a),tbl(F,/b))\");","handlingStrategy":"validation","validationCode":"String expr = CompositeInputFormat.compose(\"inner\",\n    SequenceFileInputFormat.class, \"/a\", \"/b\"); // inserts commas correctly\njob.set(\"mapred.join.expr\", expr);\ntry {\n  new CompositeInputFormat<Text>().setFormat(job); // dry-run parse\n} catch (IOException e) {\n  throw new IllegalArgumentException(\"bad join expr: \" + expr, e);\n}","typeGuard":null,"tryCatchPattern":"try {\n  new CompositeInputFormat<Object>().setFormat(job);\n} catch (IOException e) {\n  throw new IllegalArgumentException(\n      \"arguments of the join operator must be comma-separated\", e);\n}","preventionTips":["One comma between every pair of arguments, no trailing comma needed","Generate expressions with compose() rather than string concatenation","Dry-run setFormat in tests covering every shipped expression"],"tags":["hadoop","mapreduce","join","parser","expression","syntax"],"backgroundTag":"expression-parse-error","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}