eclipse-vertx/vert.x · error · IllegalArgumentException

a header value contains a prohibited character '<charCode>':

Error message

a header value contains a prohibited character '<charCode>': <seq>

What it means

Vert.x validates every character of an HTTP header value. Control characters in the 0x00–0x1F range other than HTAB (0x09), LF (0x0A) and CR (0x0D) are prohibited per RFC 7230 (field-content rules), as is DEL (0x7F). This exception is thrown when such a character is found, with its numeric code included in the message.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/HttpUtils.java:787

            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) {
      case 0x09: // Horizontal tab - HTAB
      case 0x0a: // Line feed - LF
      case 0x0d: // Carriage return - CR
        break;
      default:
        throw new IllegalArgumentException("a header value contains a prohibited character '" + (int) ch + "': " + seq);
    }
  }

  private static final boolean[] VALID_H_NAME_ASCII_CHARS;

  static {
    VALID_H_NAME_ASCII_CHARS = new boolean[Byte.MAX_VALUE + 1];
    Arrays.fill(VALID_H_NAME_ASCII_CHARS, true);
    VALID_H_NAME_ASCII_CHARS[' '] = false;
    VALID_H_NAME_ASCII_CHARS['"'] = false;
    VALID_H_NAME_ASCII_CHARS['('] = false;
    VALID_H_NAME_ASCII_CHARS[')'] = false;
    VALID_H_NAME_ASCII_CHARS[','] = false;
    VALID_H_NAME_ASCII_CHARS['/'] = false;
    VALID_H_NAME_ASCII_CHARS[':'] = false;
    VALID_H_NAME_ASCII_CHARS[';'] = false;
    VALID_H_NAME_ASCII_CHARS['<'] = false;
    VALID_H_NAME_ASCII_CHARS['>'] = false;

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Strip control characters before setting the header: value.replaceAll("[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]", "").
  2. Encode binary data as Base64 before placing it in a header.
  3. Check the reported numeric code in the message to identify which character leaked from which upstream data source.

Example fix

// before
request.putHeader("X-Data", ansiColoredLog); // contains 0x1B -> throws
// after
String clean = ansiColoredLog.replaceAll("\\x1B\\[[0-9;]*m", "").replaceAll("[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]", "");
request.putHeader("X-Data", clean);
Defensive patterns

Strategy: validation

Validate before calling

public static String sanitizeHeaderValue(String v) {
  return v.replaceAll("[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]", "");
}

Try / catch

try {
  request.putHeader(name, rawValue);
} catch (IllegalArgumentException e) {
  request.putHeader(name, sanitizeHeaderValue(rawValue));
}

Prevention

When it happens

Trigger: Putting/setting a header value that contains characters like NUL (0x00), vertical tab (0x0B), form feed (0x0C), escape (0x1B) or other control characters; thrown from HttpUtils.validateNonPrintableCtrlChar during validateHeaderValue.

Common situations: Including ANSI color escape sequences (0x1B) from terminal output in a header; passing binary/protobuf or other raw bytes decoded into a String; string data read from files or streams containing BOM/NUL 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


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/327cd3f1a80faf78. Report an issue: GitHub.