{"record":{"id":"22fd764ebbb686fb","repo":"apache/hadoop","slug":"no-key-value-to-read","errorCode":null,"errorMessage":"No key-value to read","messagePattern":"No key-value to read","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/file/tfile/TFile.java","lineNumber":1609,"sourceCode":"      }\n\n      /**\n       * Is cursor at the end location?\n       * \n       * @return true if the cursor is at the end location.\n       */\n      public boolean atEnd() {\n        return (currentLocation.compareTo(endLocation) >= 0);\n      }\n\n      /**\n       * check whether we have already successfully obtained the key. It also\n       * initializes the valueInputStream.\n       */\n      void checkKey() throws IOException {\n        if (klen >= 0) return;\n        if (atEnd()) {\n          throw new EOFException(\"No key-value to read\");\n        }\n        klen = -1;\n        vlen = -1;\n        valueChecked = false;\n\n        klen = Utils.readVInt(blkReader);\n        if (klen < 0 || klen > MAX_KEY_SIZE) {\n          throw new IOException(\"Key length out of range: \" + klen);\n        }\n        blkReader.readFully(keyBuffer, 0, klen);\n        valueBufferInputStream.reset(blkReader);\n        if (valueBufferInputStream.isLastChunk()) {\n          vlen = valueBufferInputStream.getRemain();\n        }\n      }\n\n      /**\n       * Get an entry to access the key and value.","sourceCodeStart":1591,"sourceCodeEnd":1627,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/file/tfile/TFile.java#L1591-L1627","documentation":"Thrown by Scanner.checkKey() as EOFException when a key/value read is attempted while the scanner is at or past its end location (atEnd() true). Entry material is lazily loaded: getKey()/getValue() on Scanner.Entry trigger checkKey(), and if no record remains, \"No key-value to read\" is the result. It signals normal exhaustion surfaced at the wrong layer, not file corruption.","triggerScenarios":"Calling scanner.entry().getKey() or getValue() without a preceding successful advance(); accessing the entry after advance() returned false; using a scanner created over an empty range or after seekTo parked the cursor at the end.","commonSituations":"Do-while loops that read the entry before calling advance(); ignoring the boolean returned by Scanner.advance(); assuming a seek always lands on a record when it may park at end; empty TFiles or empty scanner ranges.","solutions":["Follow the canonical loop: check the initial entry, then while (scanner.advance()) { read scanner.entry() }","Guard every entry access with !scanner.atEnd()","Treat EOFException from reads as end-of-scan and stop cleanly rather than retrying"],"exampleFix":"// before\ndo { process(scanner.entry().getKey()); } while (scanner.advance()); // EOF on empty range\n\n// after\nif (!scanner.atEnd()) {\n  process(scanner.entry().getKey());\n}\nwhile (scanner.advance()) {\n  process(scanner.entry().getKey());\n}","handlingStrategy":"validation","validationCode":"// Canonical exhaustion-safe scan loop\nScanner scanner = reader.createScanner();\nif (!scanner.atEnd()) {\n  consume(scanner.entry());\n}\nwhile (scanner.advance()) {\n  consume(scanner.entry());\n}","typeGuard":null,"tryCatchPattern":"catch (EOFException e) {\n  // \"No key-value to read\": scanner exhausted; treat as clean end-of-iteration, not an error\n}","preventionTips":["Never read scanner.entry() without either a prior successful advance() or an atEnd() check","Honor the boolean return of advance(); false means stop","After any seek, check atEnd() before touching the entry"],"tags":["hadoop","tfile","scanner","eof","iteration"],"backgroundTag":"end-of-stream","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}