apache/hadoop · error · IOException
Expected strtype
Error message
Expected strtype
What it means
Only StrToken, lexed from identifiers and double-quoted strings, supports getStr(); Token.getStr() throws IOException("Expected strtype") otherwise. The main internal caller is WNode.parse, which concatenates string tokens before the comma into the InputFormat class name, so a numeric token in the class-name position (a name starting with a digit, or a number typed where the class goes) throws this. Custom Node subclasses calling getStr() on a non-IDENT/QUOT token hit the same guard.
Source
Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/join/Parser.java:94
@InterfaceAudience.Public
@InterfaceStability.Evolving
public static class Token {
private TType type;
Token(TType type) {
this.type = type;
}
public TType getType() { return type; }
public Node getNode() throws IOException {
throw new IOException("Expected nodetype");
}
public double getNum() throws IOException {
throw new IOException("Expected numtype");
}
public String getStr() throws IOException {
throw new IOException("Expected strtype");
}
}
@InterfaceAudience.Public
@InterfaceStability.Evolving
public static class NumToken extends Token {
private double num;
public NumToken(double num) {
super(TType.NUM);
this.num = num;
}
public double getNum() { return num; }
}
@InterfaceAudience.Public
@InterfaceStability.Evolving
public static class NodeToken extends Token {
private Node node;View on GitHub (pinned to 2add963021)
Solutions
- Give the fully-qualified InputFormat class name in letters (dots inside it lex fine as one IDENT), then a comma, then a double-quoted path
- Generate the expression with CompositeInputFormat.compose() so tbl(...) clauses are always well-formed
- In custom nodes, test for TType.IDENT or TType.QUOT before calling getStr()
Example fix
// before
job.set("mapred.join.expr", "inner(tbl(123,/data),tbl(F,/data2))");
// after
job.set("mapred.join.expr",
CompositeInputFormat.compose("inner", SequenceFileInputFormat.class, "/data", "/data2")); Defensive patterns
Strategy: type-guard
Validate before calling
// in a custom Node.parse, before reading a string formal
if (!(t instanceof Parser.StrToken)
&& !(Parser.TType.IDENT.equals(t.getType()) || Parser.TType.QUOT.equals(t.getType()))) {
throw new IOException("string argument expected, got " + t.getType());
} Type guard
boolean isStrToken(Parser.Token t) {
return t instanceof Parser.StrToken; // covers IDENT and QUOT tokens
} Try / catch
try {
new CompositeInputFormat<Object>().setFormat(job);
} catch (IOException e) {
throw new IllegalArgumentException("join expression has a non-string token where a class name or path was expected", e);
} Prevention
- Keep the tbl() class-name position alphabetic (dotted FQCNs lex as one token)
- Use compose() to generate well-formed tbl clauses
- Guard getStr() with an IDENT/QUOT type check in extension nodes
When it happens
Trigger: tbl(123,"/path") or tbl(2MyFormat,"/path"): the leading number lexes as a NumToken and WNode.parse's sb.append(t.getStr()) throws; extension nodes reading a string formal that was given as a number or bare parenthesis.
Common situations: Hand-typed join expressions with numeric garbage before the comma; class names that begin with a digit; custom node formals drifting from the expression content.
Related errors
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/82a1cf8fe56764d1.
Report an issue: GitHub.