apache/hadoop · error · IOException

Expected quoted string

Error message

Expected quoted string

What it means

Thrown by the MapReduce join expression parser (Parser.WNode.parse). After the comma that ends the InputFormat class name, the parser demands a double-quoted path token (TType.QUOT). This error means the next token exists but is not a double-quoted string — typically an unquoted path or a class name given where the path belongs.

Source

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

        if (TType.COMMA.equals(t.getType())) {
          try {
          	inf = (InputFormat<?, ?>)ReflectionUtils.newInstance(
          			conf.getClassByName(sb.toString()), conf);
          } catch (ClassNotFoundException e) {
            throw new IOException(e);
          } catch (IllegalArgumentException e) {
            throw new IOException(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 Configuration getConf(Configuration jconf) throws IOException {
      Job job = Job.getInstance(jconf);
      FileInputFormat.setInputPaths(job, indir);
      return job.getConfiguration();
    }
    
    public List<InputSplit> getSplits(JobContext context)
        throws IOException, InterruptedException {
      return inf.getSplits(
                 new JobContextImpl(getConf(context.getConfiguration()), 
                                    context.getJobID()));
    }

View on GitHub (pinned to 2add963021)

Solutions

  1. Wrap every tbl() path argument in literal double quotes: tbl(<InputFormat class>, "<path>")
  2. Escape embedded quotes correctly when the expression sits inside a Java string (\") or XML config (&quot; or &amp;#34; as needed)
  3. Use CompositeInputFormat.compose(...) which generates correctly quoted tbl(...) fragments
  4. Unit-test the expression with Parser.parse(expr, conf) before job submission

Example fix

// before
String expr = "inner(tbl(TextInputFormat, /data/a), tbl(TextInputFormat, /data/b))";

// after
String expr = "inner(tbl(org.apache.hadoop.mapreduce.lib.input.TextInputFormat, \"/data/a\"),"
            + "tbl(org.apache.hadoop.mapreduce.lib.input.TextInputFormat, \"/data/b\"))";
Defensive patterns

Strategy: validation

Validate before calling

static void requireQuotedPaths(String expr) {
  // any tbl( whose second argument is not a double-quoted string
  java.util.regex.Matcher m = java.util.regex.Pattern.compile(
    "tbl\\([^,]+,\\s*([^\\\"])[^,]*\\)").matcher(expr);
  if (m.find()) throw new IllegalArgumentException(
    "tbl() path argument must be double-quoted: near '" + m.group(1) + "'");
}

Try / catch

try { Parser.parse(expr, conf); } catch (IOException e) { throw new IllegalArgumentException("Bad join expression (check quoting): " + expr, e); }

Prevention

When it happens

Trigger: The token following the COMMA in a tbl(...) node fails TType.QUOT.equals(t.getType()) at Parser.java:318. Examples: tbl(TextInputFormat, /data/a) — path not in double quotes; single quotes 'path' (the Lexer only designates '"' via tok.quoteChar('"')); tbl(fmt, tbl(...)) — nested node where a string was expected.

Common situations: Hand-writing mapreduce.join.expr and forgetting Java-style double quotes; using single quotes because the expression is embedded in another string; paths containing characters that break StreamTokenizer quoting; template code that interpolates a Path object without adding quotes.

Related errors


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