{"record":{"id":"0efb44f522b7e888","repo":"databendlabs/databend","slug":"expected-to-have-char-got-at-pos","errorCode":null,"errorMessage":"Expected to have char '{}', got '{:?}' at pos {}","messagePattern":"Expected to have char '(.+?)', got '(.+?)' at pos (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/common/io/src/cursor_ext/cursor_read_bytes_ext.rs","lineNumber":145,"sourceCode":"        self.ignore(|c| c == b)\n    }\n\n    fn ignore_bytes(&mut self, bs: &[u8]) -> bool {\n        let available = Cursor::split(self).1;\n        let len = bs.len();\n        if available.len() < len {\n            return false;\n        }\n        let eq = available[..len].iter().zip(bs).all(|(x, y)| x == y);\n        if eq {\n            BufRead::consume(self, len);\n        }\n        eq\n    }\n\n    fn must_ignore_byte(&mut self, b: u8) -> Result<()> {\n        if !self.ignore_byte(b) {\n            return Err(std::io::Error::new(\n                ErrorKind::InvalidData,\n                format!(\n                    \"Expected to have char '{}', got '{:?}' at pos {}\",\n                    b as char,\n                    self.peek(),\n                    self.position()\n                ),\n            ));\n        }\n        Ok(())\n    }\n\n    fn ignore_insensitive_bytes(&mut self, bs: &[u8]) -> bool {\n        let available = Cursor::split(self).1;\n        let len = bs.len();\n        if available.len() < len {\n            return false;\n        }","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/common/io/src/cursor_ext/cursor_read_bytes_ext.rs#L127-L163","documentation":"This is a parsing error thrown by `CursorReadBytesExt::must_ignore_byte` in databend-common-io. When a caller (e.g. `read_quoted_text` or `fast_read_quoted_text`) expects the next byte in the input cursor to be a specific character (such as an opening/closing quote), the helper consumes it if it matches; if the cursor's next byte differs, the parser aborts with the expected char, the actual peeked byte, and the cursor position.","triggerScenarios":"Calling `read_quoted_text`/`fast_read_quoted_text` on input where the byte at the current cursor position is not the expected delimiter — e.g. parsing an opening quote but the input has no quote at the start, a closing quote is missing or replaced by another character, or a malformed escape sequence shifted the cursor onto an unexpected byte.","commonSituations":"Parsing SQL-ish or serialized string values from user-supplied text (query literals, config files, CSV-like payloads) where quotes are unbalanced, single vs double quotes are mixed, or trailing whitespace/control characters sit where the parser expects a delimiter.","solutions":["Inspect the 'at pos N' value in the message and print the input around position N to see the actual byte encountered.","Ensure the input begins and ends with a matching quote character before calling read_quoted_text.","Normalize quote style (use ' or \" consistently) and strip trailing whitespace/newlines from the input.","If parsing user input, validate or pre-escape the literal before handing it to the cursor parser."],"exampleFix":"// before: parser gets non-quote byte\nlet s = \"abc\".as_bytes().read_quoted_text(&mut buf)?;\n// after: ensure the literal is quoted first\nlet input = \"abc\";\nlet s = format!(\"\\\"{}\\\"\", input).as_bytes().read_quoted_text(&mut buf)?;","handlingStrategy":"validation","validationCode":"fn ensure_quoted(input: &[u8]) -> bool {\n    let q = input.first()?;\n    (*q == b'\\'' || *q == b'\"') && input.last() == Some(q) && input.len() >= 2\n}","typeGuard":"fn is_quoted_literal(s: &str) -> bool {\n    let b = s.as_bytes();\n    b.len() >= 2 && (b[0] == b'\\'' || b[0] == b'\"') && b[b.len()-1] == b[0]\n}","tryCatchPattern":"match input.as_bytes().read_quoted_text(&mut buf) {\n    Ok(s) => s,\n    Err(e) => { log::warn!(\"literal parse failed: {e}\"); return default_literal(); }\n}","preventionTips":["Always wrap values in a matching pair of quotes before parsing.","Strip trailing whitespace/newlines from input before parsing.","Log the cursor position from the error to pinpoint malformed input."],"tags":["parsing","string-literal","rust"],"backgroundTag":"invalid-argument-value","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"}