{"record":{"id":"c4c1342e3d594e20","repo":"apache/hadoop","slug":"no-recordreader-for-ident","errorCode":null,"errorMessage":"No RecordReader for \" + ident","messagePattern":"No RecordReader for \" \\+ ident","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":326,"sourceCode":"    }\n\n    private JobConf getConf(JobConf job) {\n      JobConf conf = new JobConf(job);\n      FileInputFormat.setInputPaths(conf, indir);\n      conf.setClassLoader(job.getClassLoader());\n      return conf;\n    }\n\n    public InputSplit[] getSplits(JobConf job, int numSplits)\n        throws IOException {\n      return inf.getSplits(getConf(job), numSplits);\n    }\n\n    public ComposableRecordReader getRecordReader(\n        InputSplit split, JobConf job, Reporter reporter) throws IOException {\n      try {\n        if (!rrCstrMap.containsKey(ident)) {\n          throw new IOException(\"No RecordReader for \" + ident);\n        }\n        return rrCstrMap.get(ident).newInstance(id,\n            inf.getRecordReader(split, getConf(job), reporter), 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    }\n\n    public String toString() {\n      return ident + \"(\" + inf.getClass().getName() + \",\\\"\" + indir + \"\\\")\";\n    }\n  }\n\n  /**","sourceCodeStart":308,"sourceCodeEnd":344,"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#L308-L344","documentation":"WNode.getRecordReader looks up the ComposableRecordReader constructor registered for the wrapped node's identifier and throws IOException(\"No RecordReader for <ident>\") when rrCstrMap has no entry. In the stock flow CompositeInputFormat.setFormat calls addDefaults(), registering tbl to WrappedRecordReader before any reader is built, so this fires only when the parser tree is driven without that registration — custom code reusing Parser.WNode directly, or an extension that registers a node type without its record reader.","triggerScenarios":"Calling getRecordReader on a Parser node tree obtained outside CompositeInputFormat without calling setFormat first; a custom ComposableInputFormat that populates the node map but not the record-reader map; classpath skew where org.apache.hadoop.mapred.join classes load from two classloaders so the static maps diverge.","commonSituations":"Framework extensions and unit tests that hand-drive the parser; isolated-classloader setups such as uber-jars or nested containers.","solutions":["Go through CompositeInputFormat.setFormat(job) (or CompositeInputFormat.getRecordReader) so addDefaults() registers inner/outer/override/tbl first","In extensions, always register node and reader together via WNode.addIdentifier / CNode.addIdentifier","Ensure the join package is loaded by a single classloader in the JVM"],"exampleFix":"// before: node tree driven raw\nParser.Node root = /* obtained directly */;\nroot.getRecordReader(split, job, reporter); // No RecordReader for tbl\n\n// after: let CompositeInputFormat register identifiers first\nCompositeInputFormat<?> cif = new CompositeInputFormat<Object>();\ncif.setFormat(job);\nComposableRecordReader<?, ?> rr = cif.getRecordReader(split, job, reporter);","handlingStrategy":"validation","validationCode":"// Always initialize through CompositeInputFormat so identifiers are registered\nCompositeInputFormat<Text> cif = new CompositeInputFormat<Text>();\ncif.setFormat(job); // registers inner/outer/override/tbl via addDefaults()\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(\"identifier not registered; call CompositeInputFormat.setFormat first\", e);\n}","preventionTips":["Never call node.getRecordReader on a raw Parser tree; go through CompositeInputFormat","Register node and reader classes together via addIdentifier in extensions","Avoid loading the join package from multiple classloaders"],"tags":["hadoop","mapreduce","join","parser","registry"],"backgroundTag":"unknown-identifier","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}