pinpoint-apm/pinpoint · error · RuntimeException

RuntimeException wrapping Exception from getStatusCode

Error message

RuntimeException wrapping Exception from getStatusCode

What it means

Spring6HttpStatusProvider.getStatusCode wraps any exception thrown while reading the HTTP status of a Spring 6 ClientHttpResponse into a plain RuntimeException. The library does this to satisfy the int-returning interceptor contract while surfacing that the response object could not provide a status code. The original cause (IOException, parse failure, etc.) is preserved as the cause.

Source

Thrown at agent-module/plugins/spring-webflux/src/main/java/com/navercorp/pinpoint/plugin/spring/webflux/interceptor/util/Spring6HttpStatusProvider.java:31

 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.navercorp.pinpoint.plugin.spring.webflux.interceptor.util;

import org.springframework.http.client.reactive.ClientHttpResponse;

/**
 * @author intr3p1d
 */
public class Spring6HttpStatusProvider implements HttpStatusProvider {
    @Override
    public int getStatusCode(Object target) {
        if (target instanceof ClientHttpResponse) {
            final ClientHttpResponse response = (ClientHttpResponse) target;
            try {
                return response.getStatusCode().value();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return -1;
    }
}

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Inspect the cause (RuntimeException#getCause) to find the real I/O or parse failure
  2. Ensure the interceptor is not consuming a response stream the application also reads — avoid double-reading ClientHttpResponse
  3. Check network/proxy stability between client and server
  4. Upgrade/verify the spring-web plugin version matches the application's Spring Framework 6.x version

Example fix

// before: raw wrap loses context handling
throw new RuntimeException(e);
// after: keep interceptor contract but log the cause and return -1
try {
    return response.getStatusCode().value();
} catch (Exception e) {
    logger.warn("failed to read status code", e);
    return -1;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (target instanceof ClientHttpResponse) {
    ClientHttpResponse r = (ClientHttpResponse) target;
    try {
        r.getStatusCode();
    } catch (Exception e) {
        logger.warn("status code unreadable: {}", e.getMessage());
    }
}

Type guard

boolean isReadableResponse(Object o) {
    return o instanceof ClientHttpResponse;
}

Try / catch

try {
    int code = provider.getStatusCode(response);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    logger.warn("failed to read status code", cause);
    code = -1;
}

Prevention

When it happens

Trigger: getStatusCode(Object) is called with a ClientHttpResponse whose getStatusCode() throws — typically because the underlying stream is already consumed/closed, the connection was reset, or the response is malformed.

Common situations: WebFlux instrumentation reading the status of a response whose body/stream was already consumed by the application; network interruption mid-response; calling getStatusCode twice on a streaming response that cannot re-read it.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/4a2898c300379842. Report an issue: GitHub.