Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

[BUG] azure-core-http-netty ignores response timeout when write timeout is disabled

Cerrado
#50,795 3 comentarios 1 reacción 1 asignado Ver en GitHub

Los mantenedores suelen responder en 1 día

@alzimmermsft ya está trabajando en esto.

Desde el 14/10/2026.

  • #50821 de @alzimmermsft — abierto

Evaluación

Este issue todavía no se ha evaluado.

Descripción

Azure.Core Client customer-reported needs-team-attention question

Describe the bug

With azure-core-http-netty 1.16.5, setting writeTimeout(Duration.ZERO) also prevents the configured response timeout from firing.

I reproduced this with a WireMock endpoint that matches the request body and delays its response by one second. With a 100 ms response timeout and write timeout disabled, the request succeeds after about one second. Setting a positive write timeout makes the same request time out after about 100 ms.

Disabling the write timeout should only disable the write timeout, not the response timeout.

Exception or Stack Trace

No SDK exception is thrown in the disabled-write case. The reproducing test fails with this assertion:

org.opentest4j.AssertionFailedError: Expected java.lang.RuntimeException to be thrown, but nothing was thrown.
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:152)
	at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:73)
	at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:35)
	at org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3128)
	at AzureNettyResponseTimeoutWireMockTest.responseTimeoutShouldNotDependOnWriteTimeout(AzureNettyResponseTimeoutWireMockTest.java:53)

To Reproduce

  1. In a Java test project using azure-core-http-netty:1.16.5 and JUnit Jupiter, add the WireMock test dependency below if it is not already available.
  2. Copy the test class below into src/test/java/AzureNettyResponseTimeoutWireMockTest.java.
  3. Run mvn -Dtest=AzureNettyResponseTimeoutWireMockTest test (from the HTTP Netty module if using the SDK repository).
  4. Observe that the writeTimeoutMillis=0 case fails because no exception is thrown; the writeTimeoutMillis=5000 control case passes with the expected SDK response-timeout exception. No Azure credentials or service are required.

Verified output:

Tests run: 2, Failures: 1, Errors: 0, Skipped: 0

Maven exits with code 1 because the disabled-write case reproduces the bug.

Code Snippet

WireMock test dependency, if needed. The standalone artifact avoids changing the project's Jetty dependencies:

<dependency>
  <groupId>org.wiremock</groupId>
  <artifactId>wiremock-standalone</artifactId>
  <version>3.13.1</version>
  <scope>test</scope>
</dependency>
import com.azure.core.http.HttpClient;
import com.azure.core.http.HttpMethod;
import com.azure.core.http.HttpRequest;
import com.azure.core.http.HttpResponse;
import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
import com.github.tomakehurst.wiremock.WireMockServer;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import java.time.Duration;
import java.util.concurrent.TimeoutException;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

class AzureNettyResponseTimeoutWireMockTest {
    private WireMockServer wireMock;

    @BeforeEach
    void setUp() {
        wireMock = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").dynamicPort());
        wireMock.start();
        wireMock.stubFor(post(urlEqualTo("/timeout"))
            .withRequestBody(equalTo("payload"))
            .willReturn(aResponse().withStatus(200).withFixedDelay(1_000)));
    }

    @AfterEach
    void tearDown() {
        if (wireMock != null) wireMock.stop();
    }

    @ParameterizedTest(name = "writeTimeoutMillis={0}")
    @ValueSource(longs = {0, 5_000})
    @Timeout(10)
    void responseTimeoutShouldNotDependOnWriteTimeout(long writeTimeoutMillis) {
        HttpClient client = new NettyAsyncHttpClientBuilder()
            .writeTimeout(Duration.ofMillis(writeTimeoutMillis))
            .responseTimeout(Duration.ofMillis(100))
            .build();
        HttpRequest request = new HttpRequest(HttpMethod.POST, "http://127.0.0.1:" + wireMock.port() + "/timeout")
            .setBody("payload");

        RuntimeException failure = assertThrows(RuntimeException.class, () -> {
            try (HttpResponse ignored = client.send(request).block(Duration.ofSeconds(3))) {
                // Returning normally means the configured response timeout did not fire.
            }
        });
        Throwable root = failure;
        while (root.getCause() != null) root = root.getCause();
        assertInstanceOf(TimeoutException.class, root);
        assertTrue(root.getMessage().contains("Channel response timed out"));
    }
}

Only writeTimeout and responseTimeout are configured on the SDK client; all other client settings retain their defaults. The three-second blocking timeout is just a test safety bound, and the assertion specifically checks the SDK's response-timeout exception.

Expected behavior

Both parameterized cases should pass: with a 100 ms response timeout and a one-second server response delay, the SDK should throw a response-timeout exception whether the write timeout is enabled or disabled.

Screenshots

Not applicable.

Setup (please complete the following information):

  • OS: macOS 26.5
  • IDE: Not applicable; reproduced from the terminal using Maven.
  • Library/Libraries:
    • com.azure:azure-core-http-netty:1.16.5
    • com.azure:azure-core:1.58.1 (SDK transitive dependency)
    • io.projectreactor.netty:reactor-netty-http:1.2.18 (SDK transitive dependency)
    • org.junit.jupiter:junit-jupiter:5.13.4 (test dependency)
    • org.wiremock:wiremock-standalone:3.13.1 (test dependency)
  • Java version: Temurin OpenJDK 26.0.1+8. The reproduction compiles with Java release 17.
  • App Server/Environment: Standalone Maven/JUnit test with a local HTTP server on 127.0.0.1; no application server or Azure service.
  • Frameworks: JUnit Jupiter and WireMock. No Spring Boot or other application framework.

The standalone reproduction uses the SDK's normal transitive dependencies. No NoClassDefFoundError or NoSuchMethodError occurs in this reproduction; a dependency version mismatch is not suspected.

Additional context

The suspected cause is in Azure SDK's own AzureSdkHandler, rather than Netty or Reactor Netty:

sdk/core/azure-core-http-netty/src/main/java/com/azure/core/http/netty/implementation/AzureSdkHandler.java

Source, lines 129-138: the write-completion listener is installed only when writeTimeoutMillis > 0 at line 129. That listener also calls startResponseTracking() at line 134. When write timeout is disabled, the branch at line 138 writes without installing this listener.

Information Checklist

  • Bug Description Added
  • Repro Steps Added
  • Setup information Added
Lenguaje dominante
Java
Estrellas
2.6k
Forks
2.2k
Merge medio
1 d 18 h
PR fusionados (30 d)
231

Preparar el entorno

Abrir en Codespaces

Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de Azure/azure-sdk-for-java

Todos los issues de Azure/azure-sdk-for-java

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.