spring-boot icon indicating copy to clipboard operation
spring-boot copied to clipboard

NPE on missing status in reactive DefaultErrorAttributes

Open membersound opened this issue 3 years ago • 5 comments

I'd like to strip the reactive DefaultErrorAttributes to only expose timestamp and message fields in the json response:

@Component
public class ReactiveHidingDefaultErrorAttributes extends org.springframework.boot.web.reactive.error.DefaultErrorAttributes {
	@Override
	public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
		Map<String, Object> map = super.getErrorAttributes(request, options);
		map.keySet().retainAll(Set.of("timestamp", "message"));
		return map;
	}
}

@RestController
public class ExampleServlet {
	@GetMapping("/test")
	public Mono<String> greeting(ServerHttpRequest request) {
		if(true) throw new RuntimeException("test");
	}
}

Because especially the status field is redundant in the json rsp, as it is already send as http status code inside the response.

But if the status field is removed as written, the error handler will fail with NPE:

java.lang.NullPointerException: null
	at org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler.getHttpStatus(DefaultErrorWebExceptionHandler.java:225) ~[spring-boot-autoconfigure-2.6.3.jar:2.6.3]
	at org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler.renderErrorResponse(DefaultErrorWebExceptionHandler.java:147) ~[spring-boot-autoconfigure-2.6.3.jar:2.6.3]
	at org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler.lambda$handle$0(AbstractErrorWebExceptionHandler.java:311) ~[spring-boot-autoconfigure-2.6.3.jar:2.6.3]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onNext(FluxConcatArray.java:201) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onSubscribe(FluxConcatArray.java:193) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:258) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:78) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators.error(Operators.java:198) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoError.subscribe(MonoError.java:53) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onError(FluxDoOnEach.java:195) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:192) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:259) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators.error(Operators.java:198) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoError.subscribe(MonoError.java:53) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:192) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:259) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onError(MonoPeekTerminal.java:258) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:192) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:259) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onError(MonoIgnoreThen.java:270) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators.error(Operators.java:198) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoError.subscribe(MonoError.java:53) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onError(Operators.java:2063) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onError(MonoIgnoreThen.java:270) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onError(Operators.java:2063) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onError(MonoIgnoreThen.java:270) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onError(Operators.java:2063) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onError(MonoIgnoreThen.java:270) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:192) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:259) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:132) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onError(Operators.java:2063) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onError(MonoIgnoreThen.java:270) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators.error(Operators.java:198) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoError.subscribe(MonoError.java:53) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onError(Operators.java:2063) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onError(MonoPeekTerminal.java:258) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onError(MonoPeekTerminal.java:258) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:192) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:259) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators.error(Operators.java:198) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoError.subscribe(MonoError.java:53) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onError(MonoIgnoreThen.java:270) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:142) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoZip$ZipCoordinator.signal(MonoZip.java:251) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoZip$ZipInner.onNext(MonoZip.java:336) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.request(MonoPeekTerminal.java:139) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoZip$ZipInner.onSubscribe(MonoZip.java:325) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onSubscribe(MonoPeekTerminal.java:152) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoZip.subscribe(MonoZip.java:128) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:236) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onComplete(MonoFlatMap.java:181) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators.complete(Operators.java:137) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoZip.subscribe(MonoZip.java:120) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:255) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:282) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:863) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.request(MonoPeekTerminal.java:139) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:169) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2194) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2068) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onSubscribe(MonoPeekTerminal.java:152) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:451) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:219) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:82) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:299) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:299) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:148) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilter$FilterSubscriber.onNext(FluxFilter.java:113) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:101) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:282) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:863) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:101) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:118) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:295) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:118) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.request(FluxFilterFuseable.java:191) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:110) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onSubscribe(FluxFilterFuseable.java:87) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoCurrentContext.subscribe(MonoCurrentContext.java:36) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:118) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.request(FluxFilterFuseable.java:191) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:169) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:110) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onSubscribe(FluxFilterFuseable.java:87) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:451) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:219) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:255) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:82) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilter$FilterSubscriber.onComplete(FluxFilter.java:166) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onComplete(FluxPeekFuseable.java:940) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:85) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2194) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2068) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4400) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:82) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoNext$NextSubscriber.onComplete(MonoNext.java:102) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilter$FilterSubscriber.onComplete(FluxFilter.java:166) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:846) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:608) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:588) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onComplete(FluxFlatMap.java:465) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onComplete(FluxPeekFuseable.java:277) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:294) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:230) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:144) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:371) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:178) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onComplete(FluxDefaultIfEmpty.java:109) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxFilter$FilterSubscriber.onComplete(FluxFilter.java:166) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:269) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1817) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.signalCached(MonoCacheTime.java:337) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.onNext(MonoCacheTime.java:354) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.publisher.MonoPublishOn$PublishOnSubscriber.run(MonoPublishOn.java:181) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) [reactor-core-3.4.14.jar:3.4.14]
	at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) [reactor-core-3.4.14.jar:3.4.14]
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) [?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
	at java.lang.Thread.run(Thread.java:829) [?:?]

By the way: as an alternative, I also tried changing the ErrorAttributeOptions, but which is only suitable to hide the exception and stacktrace fields, but not the others I also want to hide:

@Component
public class ReactiveHidingDefaultErrorAttributes extends org.springframework.boot.web.reactive.error.DefaultErrorAttributes {
	@Override
	public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
		return super.getErrorAttributes(request, ErrorAttributeOptions.of(Include.MESSAGE);
	}
}

{
    "timestamp": "2022-02-21T09:19:50.745+00:00",
    "path": "/test",
    "status": 500,
    "error": "Internal Server Error",
    "message": "test",
    "requestId": "33e1262b"
}

membersound avatar Feb 21 '22 09:02 membersound

Without an HttpStatus in the error attributes, we have no way of setting the status on the server response. What did you expect the response's status to be when you'd stripped out the status attribute and how did you expect it to be set?

wilkinsona avatar Feb 28 '22 15:02 wilkinsona

Well, I simply wanted to prevent duplicate information in the returned response. As the http response status code clear, there is no need to add the status once again into the json response. Therefore trying to exclude it.

membersound avatar Mar 01 '22 13:03 membersound

At the moment, if you want to do that with WebFlux, you'll have to provide a custom ErrorWebExceptionHandler. Something like this, for example:

@Bean
@Order(-1)
ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes,
        ServerProperties serverProperties, WebProperties webProperties, ObjectProvider<ViewResolver> viewResolvers,
        ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) {
    DefaultErrorWebExceptionHandler exceptionHandler = new DefaultErrorWebExceptionHandler(errorAttributes,
            webProperties.getResources(), serverProperties.getError(), applicationContext) {

        @Override
        protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
            Map<String, Object> error = getErrorAttributes(request,
                    getErrorAttributeOptions(request, MediaType.ALL));
            int status = getHttpStatus(error);
            error.remove("status");
            return ServerResponse.status(status).contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(error));
        }

    };
    exceptionHandler.setViewResolvers(viewResolvers.orderedStream().collect(Collectors.toList()));
    exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
    exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());
    return exceptionHandler;
}

FWIW, what you tried will work with a Servlet stack, but that approach is not without its problems as described in https://github.com/spring-projects/spring-boot/issues/20504.

I'll flag this for discussion at a team meeting to see if there's anything small that we want to do in 2.x to make this easier. More major changes will have to wait for 3.0.

wilkinsona avatar Mar 01 '22 15:03 wilkinsona

your getErrorAttributes method removed status key in map . after this ,DefaultErrorWebExceptionHandler.java:225 try to get int status , then NPE.

update getErrorAttributes method, keep status key. it works.

chengjk avatar Sep 06 '22 02:09 chengjk

@chengjk Thanks for trying to help, but the reporter of the issue already knows this. They are intentionally removing the status as they consider it to be redundant information.

wilkinsona avatar Sep 06 '22 05:09 wilkinsona

I have a fix here, but it's quite a bit for a patch release and I'm starting to think it should be an enhancement in 3.4. Perhaps in 3.2 we should just protect against the NPE and use a status code of 500.

I'd like to see what the rest of the team think.

philwebb avatar Jun 15 '24 05:06 philwebb

Those changes don't look too bad to me. I'm comfortable with them going in 3.2.x in their entirety.

Perhaps in 3.2 we should just protect against the NPE and use a status code of 500

I don't think we should do this as it would mean that the reactive stack has the same problem that #20504 is tracking for the servlet stack.

wilkinsona avatar Jun 17 '24 08:06 wilkinsona