{"record":{"id":"5cf1b8ee87398e3c","repo":"twigphp/Twig","slug":"the-string-to-escape-is-not-a-valid-utf-8-string","errorCode":null,"errorMessage":"The string to escape is not a valid UTF-8 string.","messagePattern":"The string to escape is not a valid UTF-8 string\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/Runtime/EscaperRuntime.php","lineNumber":185,"sourceCode":"                    $htmlspecialcharsCharsets[$charset] = true;\n\n                    return htmlspecialchars($string, \\ENT_QUOTES | \\ENT_SUBSTITUTE, $charset);\n                }\n\n                $string = $this->convertEncoding($string, 'UTF-8', $charset);\n                $string = htmlspecialchars($string, \\ENT_QUOTES | \\ENT_SUBSTITUTE, 'UTF-8');\n\n                return iconv('UTF-8', $charset, $string);\n\n            case 'js':\n                // escape all non-alphanumeric characters\n                // into their \\x or \\uHHHH representations\n                if ('UTF-8' !== $charset) {\n                    $string = $this->convertEncoding($string, 'UTF-8', $charset);\n                }\n\n                if (!preg_match('//u', $string)) {\n                    throw new RuntimeError('The string to escape is not a valid UTF-8 string.');\n                }\n\n                $string = preg_replace_callback('#[^a-zA-Z0-9,\\._]#Su', static function ($matches) {\n                    $char = $matches[0];\n\n                    /*\n                    * A few characters have short escape sequences in JSON and JavaScript.\n                    * Escape sequences supported only by JavaScript, not JSON, are omitted.\n                    * \\\" is also supported but omitted, because the resulting string is not HTML safe.\n                    */\n                    $short = match ($char) {\n                        '\\\\' => '\\\\\\\\',\n                        '/' => '\\\\/',\n                        \"\\x08\" => '\\b',\n                        \"\\x0C\" => '\\f',\n                        \"\\x0A\" => '\\n',\n                        \"\\x0D\" => '\\r',\n                        \"\\x09\" => '\\t',","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/Runtime/EscaperRuntime.php#L167-L203","documentation":"EscaperRuntime::escape (js escaping path) requires the input string to be valid UTF-8; it converts from the configured charset to UTF-8 if needed and then runs preg_match('//u') as a validity check. On failure it throws this RuntimeError rather than emitting malformed escaped output.","triggerScenarios":"Passing a string with invalid UTF-8 bytes to the 'js' escaper (e | escape('js')) while charset is UTF-8, or a string whose declared source charset conversion still yields invalid UTF-8; commonly data read from files/DBs in another encoding or binary payloads.","commonSituations":"Legacy databases or APIs returning ISO-8859-1/Windows-1252 data not converted before rendering; user-uploaded files with mixed encodings; truncated multi-byte characters from substr() instead of mb_substr; binary blobs interpolated into templates.","solutions":["Convert the data to UTF-8 before rendering: $out = mb_convert_encoding($in, 'UTF-8', 'Windows-1252'); (or iconv)","Fix the source encoding at the connection layer (e.g. PDO mysql DSN charset=utf8mb4) or file reading (stream filter convert.iconv)","Check validity first with mb_check_encoding($s, 'UTF-8') and sanitize/reject invalid input","Ensure Twig's charset option matches your actual output encoding"],"exampleFix":"// before\n{{ legacyLatin1String|escape('js') }}\n// after\n{{ (legacyLatin1String|convert_encoding('UTF-8', 'ISO-8859-1'))|escape('js') }}","handlingStrategy":"validation","validationCode":"if (!mb_check_encoding($value, 'UTF-8')) { $value = mb_convert_encoding($value, 'UTF-8', 'Windows-1252'); }","typeGuard":"function isUtf8(string $s): bool { return mb_check_encoding($s, 'UTF-8'); }","tryCatchPattern":"try { $html = $twig->render($name, $ctx); } catch (\\Twig\\Error\\RuntimeError $e) { if (str_contains($e->getMessage(), 'valid UTF-8')) { /* sanitize/convert input and retry */ } }","preventionTips":["Validate/normalize all external data to UTF-8 before rendering","Set correct DB connection charset (utf8mb4)","Use mb_substr/mb_* string functions on multibyte data","Match Twig's charset option to actual output encoding"],"tags":["twig","escaping","utf-8","encoding","runtime-error"],"backgroundTag":"invalid-encoding","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}