apache/kafka · error · ConfigException

String may not contain control sequences but had the followi

Error message

String may not contain control sequences but had the following ASCII chars: foundIllegalCharacters.stream().map(Object::toString).collect(Collectors.joining(", "))

What it means

Thrown by NonEmptyStringWithoutControlChars.ensureValid after scanning every code point of the value with Character.isISOControl and collecting any control characters (e.g. NUL \u0000, BEL \u0007, newline \n, tab \t, escape \u001b, DEL \u007F). The message lists the decimal ASCII/Unicode code points of the offending characters. Kafka rejects these because identifier/name fields flow into protocol payloads, log lines, and JSON where control chars cause corruption or parsing failures.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java:1270

                // This can happen during creation of the config object due to no default value being defined for the
                // name configuration - a missing name parameter is caught when checking for mandatory parameters,
                // thus we can ok a null value here
                return;
            } else if (s.isEmpty()) {
                throw new ConfigException(name, value, "String may not be empty");
            }

            // Check name string for illegal characters
            ArrayList<Integer> foundIllegalCharacters = new ArrayList<>();

            for (int i = 0; i < s.length(); i++) {
                if (Character.isISOControl(s.codePointAt(i))) {
                    foundIllegalCharacters.add(s.codePointAt(i));
                }
            }

            if (!foundIllegalCharacters.isEmpty()) {
                throw new ConfigException(name, value, "String may not contain control sequences but had the following ASCII chars: " +
                        foundIllegalCharacters.stream().map(Object::toString).collect(Collectors.joining(", ")));
            }
        }

        public String toString() {
            return "non-empty string without ISO control characters";
        }
    }

    public static class ListSize implements Validator {
        final int maxSize;

        private ListSize(final int maxSize) {
            this.maxSize = maxSize;
        }

        public static ListSize atMostOfSize(final int maxSize) {
            return new ListSize(maxSize);

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Strip control characters from the value before assigning: value.replaceAll("\\p{Cntrl}", "").
  2. Re-enter the value by hand in a plain-text editor to remove hidden characters copied from rich text or spreadsheets.
  3. If the value comes from a secret/env var, trim trailing newlines: value.stripTrailing() or strip().
  4. Inspect the value with a hex dump (od -c, xxd) to locate the exact code points and their source.

Example fix

// before
// listener name copied from a spreadsheet, contains a trailing \u0007 (BEL)
props.put("advertised.listeners", "PLAINTEXT://host:9092\u0007");

// after
// sanitize or re-enter cleanly
String raw = envOrSecretValue().strip().replaceAll("\\p{Cntrl}", "");
props.put("advertised.listeners", raw);
Defensive patterns

Strategy: validation

Validate before calling

// Reject ISO control characters before Kafka sees the value:
String k = "group.id";
String v = (String) props.get(k);
if (v != null) {
    for (int i = 0; i < v.length(); i++) {
        if (Character.isISOControl(v.codePointAt(i))) {
            throw new IllegalArgumentException(k + " contains control char U+" + Integer.toHexString(v.codePointAt(i)));
        }
    }
}
// Or sanitize: v = v.replaceAll("\\p{Cc}", "");

Type guard

// A small value type that guarantees control-char-free strings:
static final class CleanStr {
    final String value;
    CleanStr(String v) {
        if (v != null) for (int i = 0; i < v.length(); i++)
            if (Character.isISOControl(v.codePointAt(i)))
                throw new IllegalArgumentException("control char at " + i);
        this.value = v;
    }
}

Try / catch

try {
    def.parse(props);
} catch (ConfigException ce) {
    if (ce.getMessage().startsWith("String may not contain control sequences")) {
        // Strip control chars and retry once
        String cleaned = ((String) ce.value()).replaceAll("\\p{Cc}", "");
        props.put(ce.getName(), cleaned);
    } else throw ce;
}

Prevention

When it happens

Trigger: A ConfigKey validated with NonEmptyStringWithoutControlChars is supplied a string containing at least one ISO control character. Triggered during ConfigDef.parse() once the empty-string check has passed. The offending characters are typically invisible in editors and logs, hence the numeric reporting.

Common situations: Copy-pasting values from rich-text editors or spreadsheets that embed formatting control chars; values sourced from secrets managers that include a trailing newline; shell commands that inject tabs or escapes; malformed multi-line properties where a continuation line break lands inside a value.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/9d0fa0e856b81ce7.json. Report an issue: GitHub.