From ba569fbfd666ff980e7b4c934c3e3c900c61f40d Mon Sep 17 00:00:00 2001 From: fei <204683769+feiiiiii5@users.noreply.github.com> Date: Sun, 20 Sep 2026 12:47:46 +0800 Subject: [PATCH] fix(gql): collapse carriage returns when sanitizing GraphQL strings strip_newlines only replaced U+000A, so a value containing CRLF or a lone CR kept a raw carriage return inside the quoted GraphQL string literal. CR is a LineTerminator in the GraphQL grammar and is not a legal unescaped character inside a string, so the server rejects the request with 'Unterminated string' rather than running the query. Text that passed through a Windows newline is the common source. --- test/test_util.py | 3 +++ weaviate/util.py | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test_util.py b/test/test_util.py index e09b52e40..91447b8b5 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -499,6 +499,9 @@ def test_is_weaviate_client_too_old(current_version: str, latest_version: str, t ('\\\\"', '\\\\\\"'), ('\\\\"', '\\\\\\"'), ('\\\\\\"', '\\\\\\"'), + ("foo\nbar", "foo bar"), + ("foo\r\nbar", "foo bar"), + ("foo\rbar", "foo bar"), ], ) def test_sanitize_str(in_str: str, out_str: str) -> None: diff --git a/weaviate/util.py b/weaviate/util.py index be61fe389..dc7ed2d49 100644 --- a/weaviate/util.py +++ b/weaviate/util.py @@ -497,7 +497,9 @@ def is_weaviate_domain(url: str) -> bool: def strip_newlines(s: str) -> str: - return s.replace("\n", " ") + # GraphQL treats CR as a line terminator inside string literals just like LF, + # so a CRLF value must collapse to one space instead of leaving a bare CR. + return s.replace("\r\n", "\n").replace("\r", "\n").replace("\n", " ") def _sanitize_str(value: str) -> str: