How to perform an action only if the Mono is empty and throw an error if not empty
Data Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.
Introduction
If a Mono contains a value, you want the pipeline to fail. If it is empty, you want to run some alternate action. In Reactor, the clean pattern is to turn the present value into Mono.error(...) and use switchIfEmpty(...) for the empty path.
The Core Reactor Idea
A Mono<T> has three possible outcomes:
- it emits one value and completes
- it completes empty
- it terminates with an error
Your requirement maps cleanly to those signals:
- non-empty means "this is forbidden, throw an error"
- empty means "run the fallback action"
That is why flatMap and switchIfEmpty are the two operators you usually need.
A Direct Solution
Suppose you query a repository and want to create a new record only when nothing already exists.
How this works:
- if
sourceemits a value,flatMapconverts that value into an error signal - if
sourceis empty,flatMaphas nothing to process and the pipeline stays empty - '
switchIfEmptythen runsperformAction()only in the empty case'
Mono.defer(...) is important when the fallback should be lazy. Without it, the fallback Mono might be assembled too early or capture side effects in ways you did not intend.
A More Realistic Example
Here is a repository-style example that returns Mono<Void>:
This reads naturally once you think in Reactor signals rather than if statements.
An Alternative Using hasElement
Sometimes you only care whether the Mono is empty, not what value it contains. In that case, hasElement() can make the intent explicit.
This style is readable, but it introduces an extra boolean stage. When you already have the original value and want to fail immediately if it exists, the flatMap plus switchIfEmpty version is usually more idiomatic.
Think in Terms of Intent
A useful way to phrase the requirement is this:
- "presence is an error"
- "absence triggers work"
Once you say it that way, the operator choice becomes much easier. Avoid trying to force imperative if else thinking into the middle of a reactive chain. Reactor becomes clearer when each branch corresponds to a signal path.
Common Pitfalls
The most common mistake is writing the fallback action eagerly instead of lazily. Use Mono.defer when the action has side effects or should only be constructed when the source is actually empty.
Another mistake is using defaultIfEmpty for this problem. defaultIfEmpty injects a value, but it does not model "do work only when empty" as clearly as switchIfEmpty.
A third pitfall is forgetting that map cannot return a Mono. If your error or fallback branch is itself reactive, use flatMap.
Summary
- Convert the non-empty case into
Mono.error(...)withflatMap. - Use
switchIfEmpty(...)for the action that should run only when the source is empty. - Wrap side-effecting fallback logic in
Mono.defer(...)so it stays lazy. - '
hasElement()can work too, butflatMapplusswitchIfEmptyis usually more idiomatic.' - Think in Reactor signals, not imperative branching.
Related reading
- How to persist a property of type ListString in JPA?
- How to POST form data with Spring RestTemplate?
- How to post request with spring boot web-client for Form data for content type application/x-www-form-urlencoded
- How to preserve insertion order in HashMap?
- How to prevent docker from starting a container automatically on system startup?
- How to prevent errno 32 broken pipe?
- How to pretty print XML from Java?
- How to prevent embedded netty server from starting with spring-boot-starter-webflux?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseData Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.