quarkusio/quarkus · error · IllegalArgumentException

Control characters not allowed in json string

Error message

Control characters not allowed in json string

What it means

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.

Source

Thrown at core/builder/src/main/java/io/quarkus/builder/JsonReader.java:207

     * |----- 'r'
     * |----- 't'
     * |----- 'u' hex hex hex hex
     */
    private JsonString readString() {
        position++;

        int start = position;
        // Substring on string values that contain unicode characters won't work,
        // because there are more characters read than actual characters represented.
        // Use StringBuilder to buffer any string read up to unicode,
        // then add unicode values into it and continue as usual.
        StringBuilder unicodeString = null;

        while (position < length) {
            final int ch = nextChar();

            if (Character.isISOControl(ch)) {
                throw new IllegalArgumentException("Control characters not allowed in json string");
            }

            if ('"' == ch) {
                final String chunk = text.substring(start, position - 1);
                final String result = unicodeString != null
                        ? unicodeString.append(chunk).toString()
                        : chunk;

                // End of string
                return new JsonString(result);
            }

            if ('\\' == ch) {
                switch (nextChar()) {
                    case '"': // quotation mark
                    case '\\': // reverse solidus
                    case '/': // solidus
                    case 'b': // backspace

View on GitHub (pinned to e1c734241f)

Solutions

  1. Replace raw control characters inside string literals with their JSON escapes: \n, \r, \t, \u0000, etc.
  2. Generate the JSON with a serializer (Jackson, jakarta.json) instead of hand-concatenating strings so escaping is automatic.
  3. Sanitize the input by stripping or escaping all characters below 0x20 before parsing.
  4. Check the source of the text (file/editor/terminal) for encoding issues that inject control bytes.

Example fix

// before (real newline byte inside the literal)
String json = "{\"msg\":\"line1
line2\"}";

// after
String json = "{\"msg\":\"line1\\nline2\"}";
Defensive patterns

Strategy: validation

Validate before calling

String sanitize(String json) {
    StringBuilder sb = new StringBuilder(json.length());
    boolean inStr = false;
    for (int i = 0; i < json.length(); i++) {
        char c = json.charAt(i);
        if (c == '"' && (i == 0 || json.charAt(i - 1) != '\\')) inStr = !inStr;
        if (inStr && c < 0x20) {
            sb.append(String.format("\\u%04x", (int) c));
        } else {
            sb.append(c);
        }
    }
    return sb.toString();
}
// parse sanitize(input) instead of input

Try / catch

try {
    JsonReader.parse(json);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Control characters")) {
        throw new ConfigException("Raw control character inside a JSON string; escape as \\n, \\t, or \\uXXXX", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/94798cf0facb5723. Report an issue: GitHub.