Skip to content

Vertx starts streaming buffer before onSuccess is completed #5825

Description

@kvr000

Version

5.0.5

Context

OS: Linux 6.17.0-6-generic #6-Ubuntu SMP PREEMPT_DYNAMIC Tue Oct 7 13:34:17 UTC 2025 x86_64 GNU/Linux (Kubuntu 25.10)
JVM: openjdk 21.0.9 2025-10-21

project link: https://github.com/kvr000/zbynek-java-exp/tree/master/http-exp/http-benchmark

In HttpClient streaming, Vertx seems to start pushing buffers prior to Future.onSuccess((HttpResponse) -> {}) is completed. As the stream handler is typically in that function, this results in loss of data:

In the github link, I provided benchmark, b3_VertxHttpClient is the randomly failing method - typically it misses about 2000 bytes - that indicates very close race condition.

In order to simulate bigger difference, I added sleep(1000) before registering onSuccess() callback and then it misses 1 GB.

Here is the additional snippet to the project:

	@Benchmark
	public void a0_VertxHttpClient(VertxHttpClientState state, Blackhole blackhole) throws Exception
	{
		MutableLong size = new MutableLong();
		Future<HttpClientResponse> future = state.httpClient.request(HttpMethod.GET, "/big_16GB")
			.compose(HttpClientRequest::send);
		Thread.sleep(1000);
		future.onSuccess((HttpClientResponse response) -> {
			if (response.statusCode() != 200) {
				Try.of(() -> { throw new IOException("Failed to retrieve file: status=" + response.statusCode()); }).get();
			}
			response.handler((buffer) -> size.add(buffer.length()));
		});
		future.await().end().await();
		if (future.await().statusCode() != 200) {
			throw new IllegalStateException("Unexpected status: " + future.await().statusCode());
		}
		if (size.longValue() != 16L*1024*1024*1024) {
			throw new IllegalStateException("Unexpected size: " + size);
		}
		blackhole.consume(size.longValue());
	}

Steps to reproduce

  1. Run the benchmark provided in the project.
  2. b3_VertxHttpClient will randomly fail with exception: java.io.IOException: Unexpected size: 17179865088

More reliable failure:

	@Benchmark
	public void a0_VertxHttpClient(VertxHttpClientState state, Blackhole blackhole) throws Exception
	{
		MutableLong size = new MutableLong();
		Future<HttpClientResponse> future = state.httpClient.request(HttpMethod.GET, "/big_16GB")
			.compose(HttpClientRequest::send);
		Thread.sleep(1000);
		future.onSuccess((HttpClientResponse response) -> {
			if (response.statusCode() != 200) {
				Try.of(() -> { throw new IOException("Failed to retrieve file: status=" + response.statusCode()); }).get();
			}
			response.handler((buffer) -> size.add(buffer.length()));
		});
		future.await().end().await();
		if (future.await().statusCode() != 200) {
			throw new IllegalStateException("Unexpected status: " + future.await().statusCode());
		}
		if (size.longValue() != 16L*1024*1024*1024) {
			throw new IllegalStateException("Unexpected size: " + size);
		}
		blackhole.consume(size.longValue());
	}

Do you have a reproducer?

https://github.com/kvr000/zbynek-java-exp/tree/master/http-exp/http-benchmark

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions