{"record":{"id":"4fdb457874c6f4c9","repo":"databendlabs/databend","slug":"expected-to-ignore-a-byte","errorCode":null,"errorMessage":"Expected to ignore a byte","messagePattern":"Expected to ignore a byte","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/common/io/src/cursor_ext/cursor_read_bytes_ext.rs","lineNumber":37,"sourceCode":"use std::io::Result;\n\npub trait ReadBytesExt {\n    fn peek(&self) -> Option<char>;\n    fn peek_byte(&self) -> Option<u8>;\n    fn ignore(&mut self, f: impl Fn(u8) -> bool) -> bool;\n    fn ignores(&mut self, f: impl Fn(u8) -> bool) -> usize;\n    fn ignore_byte(&mut self, b: u8) -> bool;\n    fn ignore_bytes(&mut self, bs: &[u8]) -> bool;\n    fn ignore_insensitive_bytes(&mut self, bs: &[u8]) -> bool;\n    fn ignore_white_spaces_or_comments(&mut self) -> bool;\n    fn ignore_comment(&mut self) -> bool;\n    fn until(&mut self, delim: u8, buf: &mut Vec<u8>) -> usize;\n    fn keep_read(&mut self, buf: &mut Vec<u8>, f: impl Fn(u8) -> bool) -> usize;\n    fn eof(&mut self) -> bool;\n    fn must_eof(&mut self) -> Result<()>;\n    fn must_ignore(&mut self, f: impl Fn(u8) -> bool) -> Result<()> {\n        if !self.ignore(f) {\n            return Err(std::io::Error::new(\n                ErrorKind::InvalidData,\n                \"Expected to ignore a byte\",\n            ));\n        }\n        Ok(())\n    }\n\n    fn must_ignore_byte(&mut self, b: u8) -> Result<()>;\n\n    fn must_ignore_bytes(&mut self, bs: &[u8]) -> Result<()> {\n        if !self.ignore_bytes(bs) {\n            return Err(std::io::Error::new(\n                ErrorKind::InvalidData,\n                format!(\"Expected to have bytes {:?}\", bs),\n            ));\n        }\n        Ok(())\n    }","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/common/io/src/cursor_ext/cursor_read_bytes_ext.rs#L19-L55","documentation":"CursorReadBytesExt::must_ignore is the fallible variant of ignore(f): it advances the cursor past the next byte if and only if that byte satisfies predicate f. If ignore returns false (EOF or predicate mismatch), it raises an InvalidData io error, since a required byte could not be skipped.","triggerScenarios":"Calling must_ignore(pred) on a cursor whose next byte does not match pred, or when the cursor is already at EOF.","commonSituations":"Parsing a structured binary/text format where a mandatory separator or padding byte is absent — often due to malformed input data or an off-by-one in the writer.","solutions":["Inspect the input at the cursor position to see which byte was expected versus found.","Use the non-panicking ignore(f) first if the byte is optional.","Fix the producer so it emits the required byte/padding."],"exampleFix":"// before\ncursor.must_ignore(|b| b == b',')?;\n\n// after\nif !cursor.ignore(|b| b == b',') {\n    // handle optional separator\n}","handlingStrategy":"validation","validationCode":"if cursor.eof() || !pred_matches_next_byte(cursor) {\n    return Err(anyhow!(\"expected separator byte\"));\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = cursor.must_ignore(|b| b == b';') {\n    return Err(anyhow!(\"parse failed at offset: {}\", e));\n}","preventionTips":["Use the non-fallible ignore() when the byte is optional.","Validate input format/version before parsing fixed-structure data.","Log cursor offset on failure to locate malformed 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"}