eclipse-vertx/vert.x · error · IllegalArgumentException
only '\n' is allowed after '\r': <seq>
Error message
only '\n' is allowed after '\r': <seq>
What it means
Vert.x validates HTTP header values to prevent header smuggling and malformed framing. When a header value contains a carriage return ('\r') that is not immediately followed by a line feed ('\n') — i.e. a bare CR — this IllegalArgumentException is thrown. Bare CR is not a legal line terminator in HTTP header values and can be used to inject headers.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/HttpUtils.java:763
}
return NO_CR_LF_STATE;
}
}
if (state != NO_CR_LF_STATE) {
// this is a rare scenario
return validateCrLfChar(seq, state, ch);
} else {
return NO_CR_LF_STATE;
}
}
private static int validateCrLfChar(CharSequence seq, int state, char ch) {
switch (state) {
case CR_STATE:
if (ch == '\n') {
return LF_STATE;
}
throw new IllegalArgumentException("only '\\n' is allowed after '\\r': " + seq);
case LF_STATE:
switch (ch) {
case '\t':
case ' ':
// return to the normal state
return NO_CR_LF_STATE;
default:
throw new IllegalArgumentException("only ' ' and '\\t' are allowed after '\\n': " + seq);
}
default:
// this should never happen
throw new AssertionError();
}
}
private static void validateNonPrintableCtrlChar(CharSequence seq, int ch) {
// The only characters allowed in the range 0x00-0x1F are : HTAB, LF and CR
switch (ch) {View on GitHub (pinned to fb308bd8c3)
Solutions
- Remove or replace bare '\r' characters from the header value (use '\n' only inside obs-fold sequences, or better, strip all line breaks).
- Sanitize the value before setting it, e.g. value.replaceAll("[\\r\\n]", " ").
- If obs-fold is intended, ensure the sequence is exactly CRLF followed by SP or HTAB ("\r\n ").
Example fix
// before
request.putHeader("X-Note", "line1\rline2"); // throws
// after
request.putHeader("X-Note", "line1\nline2".replace("\r", "")); // or replace line breaks with spaces Defensive patterns
Strategy: validation
Validate before calling
public static void checkHeaderNoBareCr(String name, String value) {
for (int i = 0; i < value.length(); i++) {
if (value.charAt(i) == '\r' && (i + 1 >= value.length() || value.charAt(i + 1) != '\n')) {
throw new IllegalArgumentException("bare CR in header " + name);
}
}
} Try / catch
try {
request.putHeader(name, value);
} catch (IllegalArgumentException e) {
log.warn("Rejecting header {} : {}", name, e.getMessage());
request.putHeader(name, sanitize(value));
} Prevention
- Sanitize all header values with a strip-CR/LF helper before setting them
- Never embed raw text from Windows-sourced data or logs directly into header values
- Treat any '\r' in dynamic input as a header-injection attempt and reject it upstream
When it happens
Trigger: Calling request.putHeader(name, value) / HttpHeaders.set or any API that writes a header whose value contains a '\r' character that is not directly followed by '\n' (e.g. "a\rb", "a\r\tb"), triggered during header validation in HttpUtils.validateValueChar/validateSequenceHeaderValue.
Common situations: Building header values by joining multi-line data with '\r' line endings (e.g. Windows-style text or log data); copying a header value captured from raw CRLF-split bytes; template strings pasted from Windows editors that embedded CR characters.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- only ' ' and '\t' are allowed after '\n': <seq>
- a header value contains a prohibited character '127': <value
- a header value must not end with '\r' or '\n':<seq>
- a header value contains a prohibited character '127': <seq>
- a header value contains a prohibited character '<charCode>':
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/b87e258794055ec7.
Report an issue: GitHub.