eclipse-vertx/vert.x · error · IllegalArgumentException

contentLength must be >= 0

Error message

contentLength must be >= 0

What it means

HttpUtils.positiveLongToString(long) converts non-negative longs to String, caching the first 256 values for hot paths (used e.g. for content-length rendering). It throws IllegalArgumentException("contentLength must be >= 0") when given a negative value, because a negative length is meaningless for HTTP message bodies. The message points at its main caller: rendering the Content-Length header of a request or response.

Source

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

   */
  public static HostAndPort socketAddressToHostAndPort(SocketAddress socketAddress) {
    if (socketAddress instanceof InetSocketAddress) {
      InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
      return new HostAndPortImpl(inetSocketAddress.getHostString(), inetSocketAddress.getPort());
    }
    return null;
  }

  private static final String[] SMALL_POSITIVE_LONGS = new String[256];

  /**
   * This try hard to cache the first 256 positive longs as strings [0, 255] to avoid the cost of creating a new
   * string for each of them.<br>
   * The size/capacity of the cache is subject to change but this method is expected to be used for hot and frequent code paths.
   */
  public static String positiveLongToString(long value) {
    if (value < 0) {
      throw new IllegalArgumentException("contentLength must be >= 0");
    }
    if (value >= SMALL_POSITIVE_LONGS.length) {
      return Long.toString(value);
    }
    final int index = (int) value;
    String str = SMALL_POSITIVE_LONGS[index];
    if (str == null) {
      // it's ok to be racy here, String is immutable hence it benefits from safe publication!
      str = Long.toString(value);
      SMALL_POSITIVE_LONGS[index] = str;
    }
    return str;
  }

  public static List<String> fromHttpAlpnVersions(List<io.vertx.core.http.HttpVersion> alpnVersions) {
    return alpnVersions
      .stream()
      .map(io.vertx.core.http.HttpVersion::alpnName)

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Find where the negative length originates (log inputs before the call) and fix the computation or initialization so the value is >= 0.
  2. Treat -1 as 'unknown length': use chunked transfer encoding (no Content-Length) instead of sending a negative value.
  3. Check that file/stream size sources (e.g. File#length) are not returning -1 for missing/unreadable resources and handle that case before writing.
  4. Guard the caller: validate length >= 0 before invoking the send/putHeader path.

Example fix

// before
long len = file.length() - offset; // can be negative
request.putHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(len));
// after
long len = file.length() - offset;
if (len < 0) {
  request.setChunked(true); // unknown length -> chunked, no Content-Length
} else {
  request.putHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(len));
}
Defensive patterns

Strategy: validation

Validate before calling

if (contentLength < 0) {
  throw new IllegalArgumentException("contentLength must be >= 0, got " + contentLength);
}
// proceed with putHeader(CONTENT_LENGTH, String.valueOf(contentLength));

Type guard

public static boolean isNonNegative(long v) { return v >= 0; }
// if (isNonNegative(len)) { putHeader(...); } else { setChunked(true); }

Try / catch

try {
  sendRequestWithLength(len);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("contentLength")) {
    log.error("Negative content length computed: {}", len);
    // resend chunked or abort with a 500
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Writing an HTTP request/response whose declared body length is negative — e.g. rendering Content-Length from a computed length of -1, passing a negative contentLength into an API that renders the header via positiveLongToString, or computing length via an underflowing subtraction (total - consumed).

Common situations: Initializing a length counter to -1 and forgetting to set it before sending; subtraction producing a negative result; file/stream size APIs returning -1 for missing or unreadable resources; a -1 'unknown length' sentinel leaking into the send path.

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/e2f5f63151d7614d. Report an issue: GitHub.