apache/hadoop · error · IOException
Expected quoted string
Error message
Expected quoted string
What it means
After the comma, WNode.parse requires the path argument to be a double-quoted string token (TType.QUOT, produced because Lexer sets quoteChar('"')). Any other token in the path position — an unquoted identifier, a number, or a parenthesis — throws IOException("Expected quoted string").
Source
Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/join/Parser.java:304
try {
inf = (InputFormat)ReflectionUtils.newInstance(
job.getClassByName(sb.toString()),
job);
} catch (ClassNotFoundException e) {
throw (IOException)new IOException().initCause(e);
} catch (IllegalArgumentException e) {
throw (IOException)new IOException().initCause(e);
}
break;
}
sb.append(t.getStr());
}
if (!i.hasNext()) {
throw new IOException("Parse error");
}
Token t = i.next();
if (!TType.QUOT.equals(t.getType())) {
throw new IOException("Expected quoted string");
}
indir = t.getStr();
// no check for ll.isEmpty() to permit extension
}
private JobConf getConf(JobConf job) {
JobConf conf = new JobConf(job);
FileInputFormat.setInputPaths(conf, indir);
conf.setClassLoader(job.getClassLoader());
return conf;
}
public InputSplit[] getSplits(JobConf job, int numSplits)
throws IOException {
return inf.getSplits(getConf(job), numSplits);
}
public ComposableRecordReader getRecordReader(View on GitHub (pinned to 2add963021)
Solutions
- Double-quote the path: tbl(F,\"/data/path\")
- Use CompositeInputFormat.compose(), which emits the quotes for you
- Remember the grammar: tbl(<class>,\"<path>\") — nothing else is accepted as the second formal
Example fix
// before
job.set("mapred.join.expr", "inner(tbl(F,/a),tbl(F,/b))");
// after
job.set("mapred.join.expr",
CompositeInputFormat.compose("inner", SequenceFileInputFormat.class, "/a", "/b")); Defensive patterns
Strategy: validation
Validate before calling
String expr = CompositeInputFormat.compose("inner",
SequenceFileInputFormat.class, "/a", "/b"); // compose() always quotes paths
if (!expr.matches("[^\"]*\"[^\"]*\"[^\"]*\\).*")) {
// lightweight sanity: at least one quoted path per tbl clause
}
job.set("mapred.join.expr", expr); Type guard
boolean isQuotedString(Parser.Token t) {
return Parser.TType.QUOT.equals(t.getType()); // only double-quoted strings
} Try / catch
try {
new CompositeInputFormat<Object>().setFormat(job);
} catch (IOException e) {
throw new IllegalArgumentException(
"tbl() path argument must be a double-quoted string", e);
} Prevention
- Only double quotes delimit strings in this grammar; single quotes are not accepted
- Use compose() which emits the quotes
- Check for quote-stripping when expressions pass through shell or template layers
When it happens
Trigger: tbl(F,/data/path) with an unquoted path; tbl(F,'/data') with single quotes, which the lexer does not treat as string delimiters; a number or parenthesis where the path should be.
Common situations: Forgetting that only double quotes delimit strings in this grammar; unquoted HDFS paths (which can also hit the '/' comment behavior and parse weirdly); expressions edited from shell snippets where the inner quotes were stripped.
Related errors
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/32236553e7ddc13f.
Report an issue: GitHub.