apache/dubbo · error · IllegalArgumentException

Negative buffer size

Error message

Negative buffer size

What it means

Thrown by the UnsafeStringWriter(int size) constructor when size < 0. The writer wraps a single StringBuilder; size is used only as the initial capacity hint passed to new StringBuilder(size). A negative capacity is invalid, so the constructor rejects it immediately rather than letting StringBuilder throw a misleading negative array size exception. The no-arg constructor UnsafeStringWriter() is unaffected.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/io/UnsafeStringWriter.java:34

 */
package org.apache.dubbo.common.io;

import java.io.IOException;
import java.io.Writer;

/**
 * Thread-unsafe StringWriter.
 */
public class UnsafeStringWriter extends Writer {
    private final StringBuilder mBuffer;

    public UnsafeStringWriter() {
        lock = mBuffer = new StringBuilder();
    }

    public UnsafeStringWriter(int size) {
        if (size < 0) {
            throw new IllegalArgumentException("Negative buffer size");
        }

        lock = mBuffer = new StringBuilder(size);
    }

    @Override
    public void write(int c) {
        mBuffer.append((char) c);
    }

    @Override
    public void write(char[] cs) throws IOException {
        mBuffer.append(cs, 0, cs.length);
    }

    @Override
    public void write(char[] cs, int off, int len) throws IOException {
        if ((off < 0) || (off > cs.length) || (len < 0) || ((off + len) > cs.length) || ((off + len) < 0)) {

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Pass a non-negative size; if you only need default capacity, use new UnsafeStringWriter() (no size).
  2. Clamp computed sizes: new UnsafeStringWriter(Math.max(0, estimatedSize)).
  3. Validate the source config value and reject/repair negative sizes upstream.
  4. Remember the size is only a capacity hint — the StringBuilder grows as needed, so 0 is always safe.

Example fix

// before
new UnsafeStringWriter(contentLength - headerOverhead) // negative when header is larger
// after
new UnsafeStringWriter(Math.max(0, contentLength - headerOverhead))
Defensive patterns

Strategy: validation

Validate before calling

if (size < 0) {
    size = 0; // capacity hint only; StringBuilder grows as needed
}
new UnsafeStringWriter(size);

Try / catch

UnsafeStringWriter w;
try {
    w = new UnsafeStringWriter(size);
} catch (IllegalArgumentException e) {
    if ("Negative buffer size".equals(e.getMessage())) {
        w = new UnsafeStringWriter(); // fall back to default capacity
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: new UnsafeStringWriter(size) with a negative size argument, e.g. new UnsafeStringWriter(-1). Typically size comes from a computed capacity (estimated payload length, header content-length, buffer config) that underflows to negative.

Common situations: Capacity estimated from a subtraction that goes negative (e.g. totalLen - overhead when overhead > totalLen); reading an untrusted/misconfigured buffer-size property; arithmetic on a length that wraps because of an empty or missing field; defaulting size to -1 as 'unspecified'.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/3ddbf31febd40521. Report an issue: GitHub.