{"record":{"id":"93743f371edb3ae9","repo":"databendlabs/databend","slug":"expected-to-have-terminated-string-literal-after-e","errorCode":null,"errorMessage":"Expected to have terminated string literal after escaped char '\\' .","messagePattern":"Expected to have terminated string literal after escaped char '\\\\' \\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/common/io/src/cursor_ext/cursor_read_string_ext.rs","lineNumber":52,"sourceCode":"impl<T> BufferReadStringExt for Cursor<T>\nwhere T: AsRef<[u8]>\n{\n    fn read_quoted_text(&mut self, buf: &mut Vec<u8>, quote: u8) -> Result<()> {\n        self.must_ignore_byte(quote)?;\n\n        loop {\n            self.keep_read(buf, |b| b != quote && b != b'\\\\');\n            if self.ignore_byte(quote) {\n                if self.peek_byte() == Some(quote) {\n                    buf.push(quote);\n                    self.consume(1);\n                } else {\n                    return Ok(());\n                }\n            } else if self.ignore_byte(b'\\\\') {\n                let b = Cursor::split(self).1;\n                if b.is_empty() {\n                    return Err(std::io::Error::new(\n                        ErrorKind::InvalidData,\n                        \"Expected to have terminated string literal after escaped char '\\' .\"\n                            .to_string(),\n                    ));\n                }\n                let c = b[0];\n                self.ignore_byte(c);\n\n                match c {\n                    b'n' => buf.push(b'\\n'),\n                    b't' => buf.push(b'\\t'),\n                    b'r' => buf.push(b'\\r'),\n                    b'0' => buf.push(b'\\0'),\n                    b'\\'' => buf.push(b'\\''),\n                    b'\\\"' => buf.push(b'\\\"'),\n                    b'\\\\' => buf.push(b'\\\\'),\n                    b'/' => buf.push(b'/'),\n                    _ => {","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/common/io/src/cursor_ext/cursor_read_string_ext.rs#L34-L70","documentation":"Thrown by `CursorReadStringExt::read_quoted_text` when it encounters a backslash escape character but the cursor is exhausted immediately after it — i.e. the input ends with a dangling `\\` and no character follows to unescape. The parser requires an escape sequence to be complete inside a quoted string literal.","triggerScenarios":"Calling `read_quoted_text` on a quoted literal whose content ends with a trailing backslash, e.g. `\"abc\\` (quote opened, backslash consumed, then end of buffer).","commonSituations":"User-provided string literals (SQL values, JSON-ish text, config entries) with an unescaped trailing backslash from a Windows path (C:\\), a truncated write, or an escaping pass that doubled up incorrectly.","solutions":["Escape the trailing backslash by doubling it: `C:\\\\` instead of `C:\\`.","Check the source string for a trailing '\\' and append a second backslash before parsing.","If the input comes from an external system, verify it was not truncated before the closing quote."],"exampleFix":"// before\nlet input = r#\"\"C:\\\"\"#; // dangling escape\n// after\nlet input = r#\"\"C:\\\\\"\"#; // escaped backslash","handlingStrategy":"validation","validationCode":"fn has_dangling_escape(s: &str) -> bool {\n    s.chars().rev().take_while(|c| *c == '\\\\').count() % 2 == 1\n}","typeGuard":"fn ends_with_complete_escape(s: &str) -> bool {\n    !has_dangling_escape(s)\n}","tryCatchPattern":"match read_quoted_text(&mut buf) {\n    Ok(s) => s,\n    Err(e) if e.to_string().contains(\"escaped char\") => {\n        // input ended with a lone backslash; fix or reject\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Double backslashes when embedding Windows-style paths in literals.","Check that literals don't end with an odd number of backslashes.","Use a shared escaping helper instead of manual string building."],"tags":["parsing","escape-sequence","string-literal"],"backgroundTag":"unterminated-string-literal","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}