{"record":{"id":"c4a1c805f375edde","repo":"apache/hadoop","slug":"iterate-past-last-value-c4a1c8","errorCode":null,"errorMessage":"iterate past last value","messagePattern":"iterate past last value","errorType":"exception","errorClass":"NoSuchElementException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/task/ReduceContextImpl.java","lineNumber":235,"sourceCode":"              clearMarkFlag = false;\n              isMarked = false;\n            }\n          }\n        } catch (IOException e) {\n          e.printStackTrace();\n          throw new RuntimeException(\"next value iterator failed\", e);\n        }\n      } \n\n      // if this is the first record, we don't need to advance\n      if (firstValue) {\n        firstValue = false;\n        return value;\n      }\n      // if this isn't the first record and the next key is different, they\n      // can't advance it here.\n      if (!nextKeyIsSame) {\n        throw new NoSuchElementException(\"iterate past last value\");\n      }\n      // otherwise, go to the next key/value pair\n      try {\n        nextKeyValue();\n        return value;\n      } catch (IOException ie) {\n        throw new RuntimeException(\"next value iterator failed\", ie);\n      } catch (InterruptedException ie) {\n        // this is bad, but we can't modify the exception list of java.util\n        throw new RuntimeException(\"next value iterator interrupted\", ie);        \n      }\n    }\n\n    @Override\n    public void remove() {\n      throw new UnsupportedOperationException(\"remove not implemented\");\n    }\n","sourceCodeStart":217,"sourceCodeEnd":253,"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/task/ReduceContextImpl.java#L217-L253","documentation":"ValueIterator.next() throws NoSuchElementException when firstValue is false and nextKeyIsSame is false — every value of the current key has been consumed. This is the standard java.util.Iterator contract firing on user reducer code that calls next() without a preceding hasNext().","triggerScenarios":"One extra values.next() after the loop; calling next() twice per a single hasNext(); caching the values iterator in the reducer and consuming it again after the group ended.","commonSituations":"Reducers that peek at the next value manually; adapting the iterator to a streaming API that calls next() eagerly; copy-paste loop constructs like do { next(); } while (hasNext()).","solutions":["Guard every next() with hasNext() evaluated in the same iteration","Use the enhanced for loop over context.values(), which enforces the contract","Never cache or re-enter the values iterator after the loop body exits"],"exampleFix":"// before\nVALUEIN v = values.next(); // called once too many after the loop\n// after\nwhile (values.hasNext()) {\n  v = values.next();\n}","handlingStrategy":"validation","validationCode":"while (values.hasNext()) {\n  VALUEIN v = values.next(); // next() only ever guarded by hasNext()\n}","typeGuard":null,"tryCatchPattern":"try {\n  v = values.next();\n} catch (NoSuchElementException e) {\n  throw new IllegalStateException(\"Values iterator exhausted for key \" + key, e);\n}","preventionTips":["Use for-each over context.values() instead of manual iterator handling","Never call next() twice per hasNext() check","Do not cache the values iterator past the loop"],"tags":["mapreduce","reducer","iterator","api-misuse","nosuchelement"],"backgroundTag":"iterate-past-end","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}