{"record":{"id":"82a1cf8fe56764d1","repo":"apache/hadoop","slug":"expected-strtype","errorCode":null,"errorMessage":"Expected strtype","messagePattern":"Expected strtype","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":94,"sourceCode":"  @InterfaceAudience.Public\n  @InterfaceStability.Evolving\n  public static class Token {\n\n    private TType type;\n\n    Token(TType type) {\n      this.type = type;\n    }\n\n    public TType getType() { return type; }\n    public Node getNode() throws IOException {\n      throw new IOException(\"Expected nodetype\");\n    }\n    public double getNum() throws IOException {\n      throw new IOException(\"Expected numtype\");\n    }\n    public String getStr() throws IOException {\n      throw new IOException(\"Expected strtype\");\n    }\n  }\n\n  @InterfaceAudience.Public\n  @InterfaceStability.Evolving\n  public static class NumToken extends Token {\n    private double num;\n    public NumToken(double num) {\n      super(TType.NUM);\n      this.num = num;\n    }\n    public double getNum() { return num; }\n  }\n\n  @InterfaceAudience.Public\n  @InterfaceStability.Evolving\n  public static class NodeToken extends Token {\n    private Node node;","sourceCodeStart":76,"sourceCodeEnd":112,"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#L76-L112","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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()"],"exampleFix":"// before\njob.set(\"mapred.join.expr\", \"inner(tbl(123,/data),tbl(F,/data2))\");\n\n// after\njob.set(\"mapred.join.expr\",\n    CompositeInputFormat.compose(\"inner\", SequenceFileInputFormat.class, \"/data\", \"/data2\"));","handlingStrategy":"type-guard","validationCode":"// in a custom Node.parse, before reading a string formal\nif (!(t instanceof Parser.StrToken)\n    && !(Parser.TType.IDENT.equals(t.getType()) || Parser.TType.QUOT.equals(t.getType()))) {\n  throw new IOException(\"string argument expected, got \" + t.getType());\n}","typeGuard":"boolean isStrToken(Parser.Token t) {\n  return t instanceof Parser.StrToken; // covers IDENT and QUOT tokens\n}","tryCatchPattern":"try {\n  new CompositeInputFormat<Object>().setFormat(job);\n} catch (IOException e) {\n  throw new IllegalArgumentException(\"join expression has a non-string token where a class name or path was expected\", e);\n}","preventionTips":["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"],"tags":["hadoop","mapreduce","join","parser","token"],"backgroundTag":"expression-parse-error","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}