{"record":{"id":"94798cf0facb5723","repo":"quarkusio/quarkus","slug":"control-characters-not-allowed-in-json-string","errorCode":null,"errorMessage":"Control characters not allowed in json string","messagePattern":"Control characters not allowed in json string","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/builder/src/main/java/io/quarkus/builder/JsonReader.java","lineNumber":207,"sourceCode":"     * |----- 'r'\n     * |----- 't'\n     * |----- 'u' hex hex hex hex\n     */\n    private JsonString readString() {\n        position++;\n\n        int start = position;\n        // Substring on string values that contain unicode characters won't work,\n        // because there are more characters read than actual characters represented.\n        // Use StringBuilder to buffer any string read up to unicode,\n        // then add unicode values into it and continue as usual.\n        StringBuilder unicodeString = null;\n\n        while (position < length) {\n            final int ch = nextChar();\n\n            if (Character.isISOControl(ch)) {\n                throw new IllegalArgumentException(\"Control characters not allowed in json string\");\n            }\n\n            if ('\"' == ch) {\n                final String chunk = text.substring(start, position - 1);\n                final String result = unicodeString != null\n                        ? unicodeString.append(chunk).toString()\n                        : chunk;\n\n                // End of string\n                return new JsonString(result);\n            }\n\n            if ('\\\\' == ch) {\n                switch (nextChar()) {\n                    case '\"': // quotation mark\n                    case '\\\\': // reverse solidus\n                    case '/': // solidus\n                    case 'b': // backspace","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/builder/src/main/java/io/quarkus/builder/JsonReader.java#L189-L225","documentation":"While scanning the characters of a JSON string literal, readString() rejects any character for which Character.isISOControl(ch) is true (control characters such as \\n, \\t, \\r, \\0 inside the raw literal). The JSON spec requires such characters to be escaped as \\uXXXX sequences, so the reader throws this IllegalArgumentException instead of accepting them.","triggerScenarios":"Calling the reader with JSON where an unescaped raw control character (newline, tab, carriage return, NUL, etc.) appears inside a quoted string, e.g. \"{\\\"key\\\":\\\"line1\\nline2\\\"}\" with a literal byte 0x0A instead of the two-character escape \\\\n.","commonSituations":"Strings built via string concatenation or templates in scripts that embed real newlines/tabs instead of escapes; JSON assembled manually in shell or config; data copied from logs or terminals that contain control bytes; binary-corrupted input files.","solutions":["Replace raw control characters inside string literals with their JSON escapes: \\n, \\r, \\t, \\u0000, etc.","Generate the JSON with a serializer (Jackson, jakarta.json) instead of hand-concatenating strings so escaping is automatic.","Sanitize the input by stripping or escaping all characters below 0x20 before parsing.","Check the source of the text (file/editor/terminal) for encoding issues that inject control bytes."],"exampleFix":"// before (real newline byte inside the literal)\nString json = \"{\\\"msg\\\":\\\"line1\nline2\\\"}\";\n\n// after\nString json = \"{\\\"msg\\\":\\\"line1\\\\nline2\\\"}\";","handlingStrategy":"validation","validationCode":"String sanitize(String json) {\n    StringBuilder sb = new StringBuilder(json.length());\n    boolean inStr = false;\n    for (int i = 0; i < json.length(); i++) {\n        char c = json.charAt(i);\n        if (c == '\"' && (i == 0 || json.charAt(i - 1) != '\\\\')) inStr = !inStr;\n        if (inStr && c < 0x20) {\n            sb.append(String.format(\"\\\\u%04x\", (int) c));\n        } else {\n            sb.append(c);\n        }\n    }\n    return sb.toString();\n}\n// parse sanitize(input) instead of input","typeGuard":null,"tryCatchPattern":"try {\n    JsonReader.parse(json);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Control characters\")) {\n        throw new ConfigException(\"Raw control character inside a JSON string; escape as \\\\n, \\\\t, or \\\\uXXXX\", e);\n    }\n    throw e;\n}","preventionTips":["Always escape control characters in string literals (\\n, \\r, \\t, \\u00XX)","Use a JSON serializer rather than hand-building strings","Check input sources (logs, terminals, editors) for injected control bytes"],"tags":["json","escaping","parser"],"backgroundTag":"unescaped-control-character-in-json","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}