apache/hadoop · error · IOException

Expected numtype

Error message

Expected numtype

What it means

Only NumToken, lexed from an unquoted numeric literal, carries a number; the base Token.getNum() throws IOException("Expected numtype"). The stock Parser never calls getNum(), so this guard exists for user extension: a custom Node subclass (registered via mapred.join.define.<ident> or addIdentifier) that reads a numeric formal hits it when the expression supplies an identifier, quoted string, or punctuation where the number was expected.

Source

Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/join/Parser.java:91

   * Tagged-union type for tokens from the join expression.
   * @see Parser.TType
   */
  @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

View on GitHub (pinned to 2add963021)

Solutions

  1. In the custom node, check Parser.Token.getType() == TType.NUM (or instanceof NumToken) before calling getNum()
  2. Fix the expression so the numeric argument is an unquoted number literal
  3. Throw a descriptive error naming the expected formal instead of relying on the generic message

Example fix

// before (custom Node.parse)
double v = t.getNum(); // throws Expected numtype on non-numeric arg

// after
if (!Parser.TType.NUM.equals(t.getType())) {
  throw new IOException("numeric argument expected, got " + t.getType());
}
double v = t.getNum();
Defensive patterns

Strategy: type-guard

Validate before calling

// in a custom Node.parse, before reading a numeric formal
for (Token t : args) {
  if (Parser.TType.NUM.equals(t.getType())) {
    double v = t.getNum();
  } else {
    throw new IOException("numeric argument expected, got " + t.getType());
  }
}

Type guard

boolean isNumToken(Parser.Token t) {
  return Parser.TType.NUM.equals(t.getType());
}

Try / catch

try {
  new CompositeInputFormat<Object>().setFormat(job);
} catch (IOException e) {
  throw new IllegalArgumentException("join expression formals do not match the custom node", e);
}

Prevention

When it happens

Trigger: A custom join node that calls t.getNum() on an argument token that is not TType.NUM, e.g. an expression myjoin(tbl(...), limit) where the node expects myjoin(tbl(...), 3).

Common situations: Extending the join grammar with numeric parameters (fan-in limits, coefficients) and passing an identifier or quoted value by mistake; evolving a custom node's expected formals without updating the expressions that use it.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/ecc9788f324dc4df. Report an issue: GitHub.