{"record":{"id":"47f34a0715167335","repo":"apache/hadoop","slug":"no-recordreader-for-47f34a","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/mapreduce/lib/join/Parser.java","lineNumber":343,"sourceCode":"    private Configuration getConf(Configuration jconf) throws IOException {\n      Job job = Job.getInstance(jconf);\n      FileInputFormat.setInputPaths(job, indir);\n      return job.getConfiguration();\n    }\n    \n    public List<InputSplit> getSplits(JobContext context)\n        throws IOException, InterruptedException {\n      return inf.getSplits(\n                 new JobContextImpl(getConf(context.getConfiguration()), \n                                    context.getJobID()));\n    }\n\n    public ComposableRecordReader<?, ?> createRecordReader(InputSplit split, \n        TaskAttemptContext taskContext) \n        throws IOException, InterruptedException {\n      try {\n        if (!rrCstrMap.containsKey(ident)) {\n          throw new IOException(\"No RecordReader for \" + ident);\n        }\n        Configuration conf = getConf(taskContext.getConfiguration());\n        TaskAttemptContext context = \n          new TaskAttemptContextImpl(conf, \n              TaskAttemptID.forName(conf.get(MRJobConfig.TASK_ATTEMPT_ID)), \n              new WrappedStatusReporter(taskContext));\n        return rrCstrMap.get(ident).newInstance(id,\n            inf.createRecordReader(split, context), cmpcl);\n      } catch (IllegalAccessException e) {\n        throw new IOException(e);\n      } catch (InstantiationException e) {\n        throw new IOException(e);\n      } catch (InvocationTargetException e) {\n        throw new IOException(e);\n      }\n    }\n\n    public String toString() {","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/join/Parser.java#L325-L361","documentation":"Parser.WNode.createRecordReader (Parser.java:343) looks up a ComposableRecordReader constructor in the rrCstrMap registry keyed by the node identifier. For wrapped nodes only 'tbl' is registered by default (CompositeInputFormat.addDefaults). The error means the identifier parsed for this wrapped node has a Node type registered but no matching ComposableRecordReader entry.","triggerScenarios":"A join expression uses a wrapped-position identifier other than 'tbl' (e.g. 'file(...)' or a custom ident) that was registered in nodeCstrMap but never got a rrCstrMap entry via addIdentifier; or custom parser extension registers a Node subclass directly without a record-reader class; classpath skew where a stale Parser subclass registered different identifiers on the client vs the task JVM.","commonSituations":"Extending the join framework with custom node types without calling Parser.WNode.addIdentifier/CNode.addIdentifier; using inner/outer/override in a tbl position or a misspelled 'tbl' ('Tbl', 'table') so it resolves to a differently-registered ident; running with mismatched Hadoop versions between job client and cluster.","solutions":["Use only the default 'tbl' identifier for wrapped inputs, e.g. tbl(fmt, \"path\")","For custom wrapped node types, register both maps: Parser.WNode.addIdentifier(\"myident\", MyWrappedRecordReader.class) via mapreduce.join.define.<ident> style extension or subclass CompositeInputFormat.addDefaults","Verify the exact identifier spelling in the expression against what addIdentifier registered","Ensure job client and cluster run the same Hadoop mapreduce-client-core version so identifier registries match"],"exampleFix":"// before\nprotected void addDefaults() {\n  super.addDefaults();\n  // custom node parsed, but no record reader registered for \"myfile\"\n  try { Parser.Node.addIdentifier(\"myfile\", new Class[]{Integer.TYPE, RecordReader.class, Class.class}, MyNode.class, null); }\n  catch (NoSuchMethodException e) { }\n}\n\n// after\nprotected void addDefaults() {\n  super.addDefaults();\n  try { Parser.WNode.addIdentifier(\"myfile\", MyWrappedRecordReader.class); }\n  catch (NoSuchMethodException e) { throw new RuntimeException(e); }\n}","handlingStrategy":"validation","validationCode":"static void requireRegisteredWrappedIdent(String ident) {\n  if (!\"tbl\".equals(ident)) {\n    throw new IllegalArgumentException(\n      \"Wrapped input ident '\" + ident + \"' has no default ComposableRecordReader; register via Parser.WNode.addIdentifier\");\n  }\n}","typeGuard":null,"tryCatchPattern":"try { cif.createRecordReader(split, ctx); } catch (IOException e) { if (e.getMessage().startsWith(\"No RecordReader\")) { /* re-register identifier, resubmit task */ } throw e; }","preventionTips":["Use only 'tbl' for wrapped inputs unless you explicitly register a custom one","Register custom wrapped identifiers via Parser.WNode.addIdentifier in an overridden CompositeInputFormat.addDefaults","Keep client and task classpaths consistent so identifier registries match"],"tags":["hadoop","mapreduce","join","record-reader","registry"],"backgroundTag":"missing-registry-entry","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}