This is an automated email from the ASF dual-hosted git repository.

quantranhong1999 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git


The following commit(s) were added to refs/heads/master by this push:
     new d1336540bb [FIX] IMAP rare NPE within processor error handling
d1336540bb is described below

commit d1336540bbb806599ff114a874caae33b6a42b1c
Author: Benoit TELLIER <[email protected]>
AuthorDate: Wed Jul 8 16:42:21 2026 +0200

    [FIX] IMAP rare NPE within processor error handling
---
 .../org/apache/james/imap/processor/AbstractMailboxProcessor.java | 6 ++++++
 .../james/imap/processor/AbstractMessageRangeProcessor.java       | 8 ++++----
 .../main/java/org/apache/james/imap/processor/CloseProcessor.java | 2 +-
 .../java/org/apache/james/imap/processor/ExpungeProcessor.java    | 2 +-
 .../java/org/apache/james/imap/processor/SearchProcessor.java     | 4 ++--
 .../main/java/org/apache/james/imap/processor/StoreProcessor.java | 4 ++--
 .../org/apache/james/imap/processor/fetch/FetchProcessor.java     | 4 ++--
 7 files changed, 18 insertions(+), 12 deletions(-)

diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
index dccf26da33..7a0e7e8d7f 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
@@ -61,6 +61,7 @@ import 
org.apache.james.mailbox.exception.InsufficientRightsException;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MessageRangeException;
 import org.apache.james.mailbox.exception.OverQuotaException;
+import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageRange.Type;
 import org.apache.james.metrics.api.MetricFactory;
@@ -388,6 +389,11 @@ public abstract class AbstractMailboxProcessor<R extends 
ImapRequest> extends Ab
         return getSelectedMailboxReactive(session, Mono.error(() -> new 
MailboxException("Session not in SELECTED state")));
     }
 
+    protected static Optional<MailboxId> selectedMailboxId(ImapSession 
session) {
+        return Optional.ofNullable(session.getSelected())
+            .map(SelectedMailbox::getMailboxId);
+    }
+
     /**
      * Return a {@link MessageRange} for the given values. If the MessageRange
      * can not be generated a {@link MailboxException} will get thrown
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java
index d933ce9468..e005df01d5 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java
@@ -98,22 +98,22 @@ public abstract class AbstractMessageRangeProcessor<R 
extends AbstractMessageRan
             .onErrorResume(MessageRangeException.class, e -> {
                 taggedBad(request, responder, 
HumanReadableText.INVALID_MESSAGESET);
                 return ReactorUtils.logAsMono(() -> LOGGER.debug("{} failed 
from mailbox {} to {} for invalid sequence-set {}",
-                    getOperationName(), session.getSelected().getMailboxId(), 
targetMailbox, request.getIdSet(), e));
+                    getOperationName(), selectedMailboxId(session), 
targetMailbox, request.getIdSet(), e));
             })
             .onErrorResume(OverQuotaException.class, e -> {
                 no(request, responder, HumanReadableText.FAILURE_OVERQUOTA, 
StatusResponse.ResponseCode.overQuota());
                 return ReactorUtils.logAsMono(() -> LOGGER.info("{} failed 
from mailbox {} to {} due to quota restriction",
-                    getOperationName(), session.getSelected().getMailboxId(), 
targetMailbox, e));
+                    getOperationName(), selectedMailboxId(session), 
targetMailbox, e));
             })
             .onErrorResume(OverQuotaException.class, e -> {
                 no(request, responder, HumanReadableText.FAILURE_OVERQUOTA, 
StatusResponse.ResponseCode.overQuota());
                 return ReactorUtils.logAsMono(() -> LOGGER.info("{} failed: 
quota exceeded from mailbox {} to {} for sequence-set {}",
-                    getOperationName(), session.getSelected().getMailboxId(), 
targetMailbox, request.getIdSet(), e.getCause()));
+                    getOperationName(), selectedMailboxId(session), 
targetMailbox, request.getIdSet(), e.getCause()));
             })
             .onErrorResume(MailboxException.class, e -> {
                 no(request, responder, 
HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING);
                 return ReactorUtils.logAsMono(() -> LOGGER.error("{} failed 
from mailbox {} to {} for sequence-set {}",
-                    getOperationName(), session.getSelected().getMailboxId(), 
targetMailbox, request.getIdSet(), e.getCause()));
+                    getOperationName(), selectedMailboxId(session), 
targetMailbox, request.getIdSet(), e.getCause()));
             }).then();
     }
 
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/CloseProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/CloseProcessor.java
index fd38286a4e..65a7538a62 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/CloseProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/CloseProcessor.java
@@ -78,7 +78,7 @@ public class CloseProcessor extends 
AbstractMailboxProcessor<CloseRequest> {
             }))
             .onErrorResume(MailboxException.class, e -> {
                 no(request, responder, 
HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING);
-                return ReactorUtils.logAsMono(() -> LOGGER.error("Close failed 
for mailbox {}", session.getSelected().getMailboxId(), e));
+                return ReactorUtils.logAsMono(() -> LOGGER.error("Close failed 
for mailbox {}", selectedMailboxId(session), e));
             }).then();
     }
 
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java
index abdcb4cf3d..9c302e9bda 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java
@@ -89,7 +89,7 @@ public class ExpungeProcessor extends 
AbstractMailboxProcessor<ExpungeRequest> i
             })
             .onErrorResume(MailboxException.class, e -> {
                 no(request, responder, 
HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING);
-                return ReactorUtils.logAsMono(() -> LOGGER.error("Expunge 
failed for mailbox {}", session.getSelected().getMailboxId(), e));
+                return ReactorUtils.logAsMono(() -> LOGGER.error("Expunge 
failed for mailbox {}", selectedMailboxId(session), e));
             });
     }
 
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
index 2843aa3cfc..ae8721651a 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
@@ -127,10 +127,10 @@ public class SearchProcessor extends 
AbstractMailboxProcessor<SearchRequest> imp
                         // See RFC5182 2.1.Normative Description of the 
SEARCHRES Extension
                         SearchResUtil.resetSavedSequenceSet(session);
                     }
-                    return ReactorUtils.logAsMono(() -> LOGGER.error("Search 
failed in mailbox {}", session.getSelected().getMailboxId(), e));
+                    return ReactorUtils.logAsMono(() -> LOGGER.error("Search 
failed in mailbox {}", selectedMailboxId(session), e));
                 });
         } catch (MessageRangeException e) {
-            return ReactorUtils.logAsMono(() -> LOGGER.debug("Search failed in 
mailbox {} because of an invalid sequence-set ", 
session.getSelected().getMailboxId(), e))
+            return ReactorUtils.logAsMono(() -> LOGGER.debug("Search failed in 
mailbox {} because of an invalid sequence-set ", selectedMailboxId(session), e))
                 .then(Mono.fromRunnable(() -> taggedBad(request, responder, 
HumanReadableText.INVALID_MESSAGESET)));
         }
     }
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
index 1d136cacaa..89ed89190e 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
@@ -118,11 +118,11 @@ public class StoreProcessor extends 
AbstractMailboxProcessor<StoreRequest> {
             })
             .onErrorResume(MessageRangeException.class, e -> {
                 taggedBad(request, responder, 
HumanReadableText.INVALID_MESSAGESET);
-                return ReactorUtils.logAsMono(() -> LOGGER.debug("Store failed 
for mailbox {} because of an invalid sequence-set {}", 
session.getSelected().getMailboxId(), idSet, e));
+                return ReactorUtils.logAsMono(() -> LOGGER.debug("Store failed 
for mailbox {} because of an invalid sequence-set {}", 
selectedMailboxId(session), idSet, e));
             })
             .onErrorResume(MailboxException.class, e -> {
                 no(request, responder, HumanReadableText.SAVE_FAILED);
-                return ReactorUtils.logAsMono(() -> LOGGER.error("Store failed 
for mailbox {} and sequence-set {}", session.getSelected().getMailboxId(), 
idSet, e));
+                return ReactorUtils.logAsMono(() -> LOGGER.error("Store failed 
for mailbox {} and sequence-set {}", selectedMailboxId(session), idSet, e));
             });
     }
 
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
index 2d1d8de2cd..3be25820c7 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
@@ -261,13 +261,13 @@ public class FetchProcessor extends 
AbstractMailboxProcessor<FetchRequest> {
             .<SelectedMailbox>handle((a, sink) -> 
a.ifPresentOrElse(sink::next, () -> sink.error(new MailboxException("Session 
not in SELECTED state"))))
             .flatMap(selected -> processFetch(request, session, responder, 
selected, fetch, changedSince))
             .doOnEach(logOnError(MessageRangeException.class, e -> 
LOGGER.debug("Fetch failed for mailbox {} because of invalid sequence-set {}",
-                
Optional.ofNullable(session.getSelected()).map(SelectedMailbox::getMailboxId), 
idSet, e)))
+                selectedMailboxId(session), idSet, e)))
             .onErrorResume(MessageRangeException.class, e -> {
                 taggedBad(request, responder, 
HumanReadableText.INVALID_MESSAGESET);
                 return Mono.empty();
             })
             .doOnEach(logOnError(MailboxException.class, e -> 
LOGGER.error("Fetch failed for mailbox {} and sequence-set {}",
-                
Optional.ofNullable(session.getSelected()).map(SelectedMailbox::getMailboxId), 
idSet, e)))
+                selectedMailboxId(session), idSet, e)))
             .onErrorResume(MailboxException.class, e -> {
                 no(request, responder, HumanReadableText.SEARCH_FAILED);
                 return Mono.empty();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to