apache/hadoop · error · IOException
Expected ','
Error message
Expected ','
What it means
Parser.CNode.parse (Parser.java:502) parses the comma-separated child list of a composite join operator like inner(...). After reading each child node it expects the next token to be a COMMA. Anything else (another node, a path, an unbalanced token) throws 'Expected \',\''.
Source
Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/join/Parser.java:502
}
for (int i = 0; i < capacity; ++i) {
ret.add(kids.get(i).createRecordReader(spl.get(i), taskContext));
}
return (ComposableRecordReader)ret;
}
/**
* Parse a list of comma-separated nodes.
*/
public void parse(List<Token> args, Configuration conf)
throws IOException {
ListIterator<Token> i = args.listIterator();
while (i.hasNext()) {
Token t = i.next();
t.getNode().setID(i.previousIndex() >> 1);
kids.add(t.getNode());
if (i.hasNext() && !TType.COMMA.equals(i.next().getType())) {
throw new IOException("Expected ','");
}
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(ident + "(");
for (Node n : kids) {
sb.append(n.toString() + ",");
}
sb.setCharAt(sb.length() - 1, ')');
return sb.toString();
}
}
private static Token reduce(Stack<Token> st, Configuration conf)
throws IOException {
LinkedList<Token> args = new LinkedList<Token>();View on GitHub (pinned to 2add963021)
Solutions
- Separate every child node inside inner(...)/outer(...)/override(...) with a single comma: inner(tbl(...),tbl(...))
- Remove trailing commas and stray tokens after the final child
- Generate the expression with CompositeInputFormat.compose(op, infClass, paths...) which emits correct separators
- Dry-run Parser.parse(expr, conf) in a unit test to catch syntax errors before submission
Example fix
// before
conf.set("mapreduce.join.expr",
"outer(tbl(fmt, \"/a\") tbl(fmt, \"/b\"))");
// after
conf.set("mapreduce.join.expr",
"outer(tbl(fmt, \"/a\"), tbl(fmt, \"/b\"))"); Defensive patterns
Strategy: validation
Validate before calling
static String buildJoinExpr(String op, List<String> children) {
for (String c : children) if (c == null || c.trim().isEmpty()) throw new IllegalArgumentException("null/empty join child");
return op + "(" + String.join(",", children) + ")"; // always emits commas
} Try / catch
try { Parser.parse(expr, conf); } catch (IOException e) { throw new IllegalArgumentException("Join expression syntax error (check commas between children): " + expr, e); } Prevention
- Separate every child inside operator calls with exactly one comma
- No trailing comma after the last child
- Generate with CompositeInputFormat.compose() and lint hand-written strings
When it happens
Trigger: Children of inner/outer/override not separated by commas: 'inner(tbl(fmt,"/a") tbl(fmt,"/b"))'; a trailing token after the last child: 'inner(a,b,)'; stray identifiers inside the operator call. The loop at Parser.java:496-504 consumes node, then i.next() must be COMMA whenever i.hasNext().
Common situations: Hand-writing mapreduce.join.expr and using spaces instead of commas; editing an expression and dropping a comma; building the string with a join/loop that omits separators on some boundary; whitespace/formatting changes that introduce extra tokens.
Related errors
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/a316fa2b872e5d5d.
Report an issue: GitHub.