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

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


The following commit(s) were added to refs/heads/3.9.x by this push:
     new c00729db6f [FIX] Handle partial rows in attachmentV2
c00729db6f is described below

commit c00729db6fbf9af2cded18cbf30df57b442c27cb
Author: Benoit TELLIER <[email protected]>
AuthorDate: Mon Aug 17 20:23:14 2026 +0700

    [FIX] Handle partial rows in attachmentV2
    
    (cherry picked from commit 98c4277affb947b7b844d7fa47418dcfe863cf8b)
---
 .../mailbox/cassandra/mail/CassandraAttachmentDAOV2.java | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git 
a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
 
b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
index 2a1b9f0e27..4ee7978409 100644
--- 
a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
+++ 
b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
@@ -48,6 +48,8 @@ import org.apache.james.mailbox.model.ContentType;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.StringBackedAttachmentId;
 import org.apache.james.util.DurationParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.datastax.oss.driver.api.core.CqlSession;
 import com.datastax.oss.driver.api.core.cql.PreparedStatement;
@@ -59,6 +61,7 @@ import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
 public class CassandraAttachmentDAOV2 {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(CassandraAttachmentDAOV2.class);
     private static final Optional<Duration> TTL = 
Optional.ofNullable(System.getProperty("james.jmap.attachment.ttl", null))
         .map(DurationParser::parse);
 
@@ -135,6 +138,14 @@ public class CassandraAttachmentDAOV2 {
             attachment.getSize());
     }
 
+    private static boolean isWellFormed(Row row, AttachmentId attachmentId) {
+        if (row.getString(ID) == null || row.getString(BLOB_ID) == null) {
+            LOGGER.warn("Ignoring partially written attachment row {}", 
attachmentId.getId());
+            return false;
+        }
+        return true;
+    }
+
     private static DAOAttachment fromRow(Row row, BlobId.Factory 
blobIfFactory) {
         MessageId messageId = 
CassandraMessageId.Factory.of(row.getUuid(MESSAGE_ID));
 
@@ -204,6 +215,7 @@ public class CassandraAttachmentDAOV2 {
         return cassandraAsyncExecutor.executeSingleRow(
                 selectStatement.bind()
                     .setUuid(ID_AS_UUID, attachmentId.asUUID()))
+            .filter(row -> isWellFormed(row, attachmentId))
             .map(row -> CassandraAttachmentDAOV2.fromRow(row, blobIdFactory));
     }
 
@@ -227,6 +239,8 @@ public class CassandraAttachmentDAOV2 {
 
     public Flux<BlobId> listBlobs() {
         return cassandraAsyncExecutor.executeRows(listBlobs.bind())
-            .map(row -> blobIdFactory.parse(row.getString(BLOB_ID)));
+            .map(row -> row.getString(BLOB_ID))
+            .filter(Objects::nonNull)
+            .map(blobIdFactory::parse);
     }
 }


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

Reply via email to