You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Reactor:如何在反应式代码中正确抛出RuntimeException?

How to Propagate RuntimeException from Reactor Stream in createImage Method

Let's break down how to solve your problem where you want to directly throw the RuntimeException you created in decodeColour instead of getting an ErrorCallbackNotImplemented error.

Root Cause of the Issue

When you call subscribe() without specifying an error handler, Reactor doesn't have a way to route the error from your stream—it wraps the original exception in ErrorCallbackNotImplemented as a warning that you didn't handle errors in your subscription. doOnError only runs side-effect logic when an error occurs, but it doesn't stop the error from reaching the subscriber, so you still get that unhandled error exception.

Solution 1: Explicitly Handle Errors in subscribe()

Modify your subscribe() call to include an error consumer that re-throws your RuntimeException (or wraps other errors if needed). This ensures the error is propagated instead of being wrapped:

public void createImage(Image image) {
    tokenProvider.getAccessToken()
        .flatMap(accessToken -> restClient.decodeColour(url, accessToken.getToken())
            .flatMap(colour -> restClient.createImage(url, accessToken.getToken())))
        .subscribe(
            // Handle success case (can leave empty if no action needed)
            result -> {},
            // Handle error and re-throw your RuntimeException
            error -> {
                if (error instanceof RuntimeException) {
                    throw (RuntimeException) error;
                } else {
                    // Wrap unexpected errors if needed
                    throw new RuntimeException("Unexpected error during image creation", error);
                }
            }
        );
}

Note: If this runs in an asynchronous thread, make sure your application has a mechanism to catch uncaught exceptions (Spring's error handling usually covers this in WebFlux contexts).

Instead of making the method void, return a Mono<Void> to let the caller handle the error propagation. This aligns with Reactor's asynchronous programming model and avoids manual subscription pitfalls:

public Mono<Void> createImage(Image image) {
    return tokenProvider.getAccessToken()
        .flatMap(accessToken -> restClient.decodeColour(url, accessToken.getToken())
            .flatMap(colour -> restClient.createImage(url, accessToken.getToken())))
        .then(); // Convert the stream to a completion signal (Mono<Void>)
}

When you return this Mono from a Spring WebFlux controller or another reactive component, the framework will automatically handle error propagation—your RuntimeException will be converted to an appropriate HTTP error response, or the caller can subscribe with their own error handler.

If you absolutely need to block the thread and throw the exception synchronously (this defeats WebFlux's non-blocking purpose, so use only if forced):

public void createImage(Image image) {
    try {
        tokenProvider.getAccessToken()
            .flatMap(accessToken -> restClient.decodeColour(url, accessToken.getToken())
                .flatMap(colour -> restClient.createImage(url, accessToken.getToken())))
            .block(); // Blocks until the stream completes or errors
    } catch (RuntimeException e) {
        throw e; // Re-throw your custom RuntimeException
    }
}

Key Takeaway

The best practice for WebFlux is Solution 2—returning a reactive type lets the framework handle error flow properly. If you must use a void method, go with Solution 1 to explicitly handle and re-throw errors in your subscription.

内容的提问来源于stack exchange,提问作者Aleksandar Grujic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:57:29