{"record":{"id":"70af3cc4fcd5830e","repo":"databendlabs/databend","slug":"must-reach-the-buffer-end","errorCode":null,"errorMessage":"Must reach the buffer end","messagePattern":"Must reach the buffer end","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/common/io/src/cursor_ext/cursor_read_bytes_ext.rs","lineNumber":90,"sourceCode":"        let buf = Cursor::split(self).1;\n        if buf.is_empty() {\n            None\n        } else {\n            Some(buf[0] as char)\n        }\n    }\n\n    fn peek_byte(&self) -> Option<u8> {\n        let buf = Cursor::split(self).1;\n        if buf.is_empty() { None } else { Some(buf[0]) }\n    }\n\n    fn eof(&mut self) -> bool {\n        Cursor::split(self).1.is_empty()\n    }\n    fn must_eof(&mut self) -> Result<()> {\n        if !Cursor::split(self).1.is_empty() {\n            return Err(std::io::Error::new(\n                ErrorKind::InvalidData,\n                \"Must reach the buffer end\",\n            ));\n        }\n        Ok(())\n    }\n\n    fn ignore(&mut self, f: impl Fn(u8) -> bool) -> bool {\n        let available = Cursor::split(self).1;\n        if available.is_empty() {\n            false\n        } else if f(available[0]) {\n            self.consume(1);\n            true\n        } else {\n            false\n        }\n    }","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/common/io/src/cursor_ext/cursor_read_bytes_ext.rs#L72-L108","documentation":"CursorReadBytesExt::must_eof asserts the cursor has consumed its entire underlying buffer. If unread bytes remain after a parse, it raises an InvalidData io error, enforcing that the input contained nothing beyond the expected structure.","triggerScenarios":"Calling must_eof() when the cursor still holds unconsumed bytes — e.g. trailing characters/garbage after the parsed value or an incomplete parse that stopped early.","commonSituations":"Strict parsers validating user-supplied strings or binary payloads where trailing whitespace, extra tokens, or wrong-format suffixes remain unconsumed.","solutions":["Inspect the remaining bytes (Cursor::split(self).1) to see what trailing data was left.","Explicitly consume/ignore allowed trailing content (e.g. whitespace) before calling must_eof.","Fix the parser to consume all expected tokens, or relax to eof() if trailing data is acceptable."],"exampleFix":"// before\ncursor.must_eof()?;\n\n// after\ncursor.keep_read(&mut Vec::new(), |b| b.is_ascii_whitespace());\ncursor.must_eof()?;","handlingStrategy":"validation","validationCode":"if !cursor.eof() {\n    return Err(anyhow!(\"trailing input after parsed value\"));\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = cursor.must_eof() {\n    return Err(anyhow!(\"trailing data: {}\", e));\n}","preventionTips":["Trim or explicitly consume allowed trailing whitespace before must_eof.","Use the boolean eof() when trailing content is acceptable.","Log remaining bytes on failure to identify unconsumed input."],"tags":["parsing","io","rust","cursor"],"backgroundTag":"invalid-argument-format","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}