{"record":{"id":"6f18b900d4606ce4","repo":"apache/hadoop","slug":"no-recordreader-for","errorCode":null,"errorMessage":"No RecordReader for {}","messagePattern":"No RecordReader for (.+?)","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":413,"sourceCode":"          ret[i].add(splits[j][i]);\n        }\n      }\n      return ret;\n    }\n\n    @SuppressWarnings(\"unchecked\") // child types unknowable\n    public ComposableRecordReader getRecordReader(\n        InputSplit split, JobConf job, Reporter reporter) throws IOException {\n      if (!(split instanceof CompositeInputSplit)) {\n        throw new IOException(\"Invalid split type:\" +\n                              split.getClass().getName());\n      }\n      final CompositeInputSplit spl = (CompositeInputSplit)split;\n      final int capacity = kids.size();\n      CompositeRecordReader ret = null;\n      try {\n        if (!rrCstrMap.containsKey(ident)) {\n          throw new IOException(\"No RecordReader for \" + ident);\n        }\n        ret = (CompositeRecordReader)\n          rrCstrMap.get(ident).newInstance(id, job, capacity, cmpcl);\n      } catch (IllegalAccessException e) {\n        throw (IOException)new IOException().initCause(e);\n      } catch (InstantiationException e) {\n        throw (IOException)new IOException().initCause(e);\n      } catch (InvocationTargetException e) {\n        throw (IOException)new IOException().initCause(e);\n      }\n      for (int i = 0; i < capacity; ++i) {\n        ret.add(kids.get(i).getRecordReader(spl.get(i), job, reporter));\n      }\n      return (ComposableRecordReader)ret;\n    }\n\n    /**\n     * Parse a list of comma-separated nodes.","sourceCodeStart":395,"sourceCodeEnd":431,"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#L395-L431","documentation":"CNode.getRecordReader resolves the composite operator (inner/outer/override or a mapred.join.define identifier) to a ComposableRecordReader constructor via rrCstrMap, throwing IOException(\"No RecordReader for <ident>\") when the identifier is absent. As with the wrapped-node variant, the stock flow registers these in CompositeInputFormat.setFormat before readers are created, so this indicates the node tree was driven without registration, or an extension split the node/reader registration, or classloader duplication diverged the static maps.","triggerScenarios":"Custom code obtaining a Parser.CNode and calling getRecordReader without CompositeInputFormat.setFormat; an extension registering only the node constructor for an identifier; the join package loaded by two classloaders so the static rrCstrMap seen by the reader differs from the one used at parse time.","commonSituations":"Framework extensions and unit tests that hand-drive the parser; custom operators defined via mapred.join.define in one conf but executed with another; application-server style classloader isolation.","solutions":["Call setFormat(job) — or run through CompositeInputFormat.getRecordReader — so identifiers are registered first","Register custom operators with mapred.join.define.<ident> pointing at a ComposableRecordReader exposing the (int, JobConf, int, Class) constructor","Ensure a single classloader loads the join package"],"exampleFix":"// before\nParser.Node root = /* CNode obtained directly */;\nroot.getRecordReader(split, job, reporter); // No RecordReader for inner\n\n// after\nCompositeInputFormat<?> cif = new CompositeInputFormat<Object>();\ncif.setFormat(job); // registers inner/outer/override/tbl\nComposableRecordReader<?, ?> rr = cif.getRecordReader(split, job, reporter);","handlingStrategy":"validation","validationCode":"// initialize identifiers before any reader construction\nCompositeInputFormat<Text> cif = new CompositeInputFormat<Text>();\ncif.setFormat(job); // addDefaults() + mapred.join.define.* registered here\nComposableRecordReader<Text, TupleWritable> rr =\n    cif.getRecordReader(split, job, reporter);","typeGuard":null,"tryCatchPattern":"try {\n  return root.getRecordReader(split, job, reporter);\n} catch (IOException e) {\n  throw new IOException(\"composite operator not registered; run through \"\n      + \"CompositeInputFormat.setFormat or add mapred.join.define.<ident>\", e);\n}","preventionTips":["Always route reader construction through CompositeInputFormat.getRecordReader","Give custom operators a (int, JobConf, int, Class) constructor and register them via mapred.join.define","Prevent multi-classloader loading of the join package"],"tags":["hadoop","mapreduce","join","parser","registry"],"backgroundTag":"unknown-identifier","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}