diff --git a/briar-api/src/org/briarproject/api/clients/BdfMessageContext.java b/briar-api/src/org/briarproject/api/clients/BdfMessageContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..d856c973c81d3ca9c46d9bb6a70b5e3fae60a62a
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/clients/BdfMessageContext.java
@@ -0,0 +1,28 @@
+package org.briarproject.api.clients;
+
+import org.briarproject.api.data.BdfDictionary;
+import org.briarproject.api.sync.BaseMessageContext;
+import org.briarproject.api.sync.MessageId;
+
+import java.util.Collection;
+
+public class BdfMessageContext extends BaseMessageContext {
+
+	private final BdfDictionary dictionary;
+
+	public BdfMessageContext(BdfDictionary dictionary,
+			Collection<MessageId> dependencies) {
+
+		super(dependencies);
+		this.dictionary = dictionary;
+	}
+
+	public BdfMessageContext(BdfDictionary dictionary) {
+		this(dictionary, null);
+	}
+
+	public BdfDictionary getDictionary() {
+		return dictionary;
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java b/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java
index 52bb298ac466347bd54e600e8c2271244273a41d..1d989d75fbee8feef3e6f2f9619b5341f261db84 100644
--- a/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java
+++ b/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java
@@ -5,6 +5,8 @@ import org.briarproject.api.db.Metadata;
 import org.briarproject.api.db.Transaction;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
+import org.briarproject.api.sync.InvalidMessageException;
+import org.briarproject.api.sync.MessageContext;
 
 public interface MessageQueueManager {
 
@@ -34,10 +36,11 @@ public interface MessageQueueManager {
 	interface QueueMessageValidator {
 
 		/**
-		 * Validates the given message and returns its metadata if the message
-		 * is valid, or null if the message is invalid.
+		 * Validates the given message and returns its metadata and
+		 * dependencies.
 		 */
-		Metadata validateMessage(QueueMessage q, Group g);
+		MessageContext validateMessage(QueueMessage q, Group g)
+				throws InvalidMessageException;
 	}
 
 	interface IncomingQueueMessageHook {
diff --git a/briar-api/src/org/briarproject/api/sync/BaseMessageContext.java b/briar-api/src/org/briarproject/api/sync/BaseMessageContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..de574b7c16a155d144a8543cb0ecde28bf054b7a
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/sync/BaseMessageContext.java
@@ -0,0 +1,17 @@
+package org.briarproject.api.sync;
+
+import java.util.Collection;
+
+public abstract class BaseMessageContext {
+
+	private final Collection<MessageId> dependencies;
+
+	public BaseMessageContext(Collection<MessageId> dependencies) {
+		this.dependencies = dependencies;
+	}
+
+	public Collection<MessageId> getDependencies() {
+		return dependencies;
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/sync/InvalidMessageException.java b/briar-api/src/org/briarproject/api/sync/InvalidMessageException.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa8b669ca79ef9e6af53acc4a06ab5f6cb804890
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/sync/InvalidMessageException.java
@@ -0,0 +1,20 @@
+package org.briarproject.api.sync;
+
+import java.io.IOException;
+
+/** An exception that indicates an invalid message. */
+public class InvalidMessageException extends IOException {
+
+	public InvalidMessageException() {
+		super();
+	}
+
+	public InvalidMessageException(String str) {
+		super(str);
+	}
+
+	public InvalidMessageException(Throwable t) {
+		super(t);
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/sync/MessageContext.java b/briar-api/src/org/briarproject/api/sync/MessageContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..35f45e76caa6b560014191d8c21a1c3573c5d558
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/sync/MessageContext.java
@@ -0,0 +1,26 @@
+package org.briarproject.api.sync;
+
+import org.briarproject.api.db.Metadata;
+
+import java.util.Collection;
+
+public class MessageContext extends BaseMessageContext {
+
+	private final Metadata metadata;
+
+	public MessageContext(Metadata metadata,
+			Collection<MessageId> dependencies) {
+
+		super(dependencies);
+		this.metadata = metadata;
+	}
+
+	public MessageContext(Metadata metadata) {
+		this(metadata, null);
+	}
+
+	public Metadata getMetadata() {
+		return metadata;
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/sync/ValidationManager.java b/briar-api/src/org/briarproject/api/sync/ValidationManager.java
index abea827e2b2f7ba2eccd0cab10844598000f2b33..7304b2e038254426500eb2110889ec47f5a0bb5b 100644
--- a/briar-api/src/org/briarproject/api/sync/ValidationManager.java
+++ b/briar-api/src/org/briarproject/api/sync/ValidationManager.java
@@ -44,10 +44,11 @@ public interface ValidationManager {
 	interface MessageValidator {
 
 		/**
-		 * Validates the given message and returns its metadata if the message
-		 * is valid, or null if the message is invalid.
+		 * Validates the given message and returns its metadata and
+		 * dependencies.
 		 */
-		Metadata validateMessage(Message m, Group g);
+		MessageContext validateMessage(Message m, Group g)
+				throws InvalidMessageException;
 	}
 
 	interface IncomingMessageHook {
diff --git a/briar-core/src/org/briarproject/clients/BdfMessageValidator.java b/briar-core/src/org/briarproject/clients/BdfMessageValidator.java
index 19bc55db000f1dd841167c6f3eb4d0fd03a514e5..0ebcbfb15595214d2807373513d7f22f2c94479c 100644
--- a/briar-core/src/org/briarproject/clients/BdfMessageValidator.java
+++ b/briar-core/src/org/briarproject/clients/BdfMessageValidator.java
@@ -4,13 +4,16 @@ import org.briarproject.api.FormatException;
 import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.clients.MessageQueueManager.QueueMessageValidator;
 import org.briarproject.api.clients.QueueMessage;
+import org.briarproject.api.clients.BdfMessageContext;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.MetadataEncoder;
 import org.briarproject.api.db.Metadata;
 import org.briarproject.api.sync.Group;
+import org.briarproject.api.sync.InvalidMessageException;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.ValidationManager.MessageValidator;
+import org.briarproject.api.sync.MessageContext;
 import org.briarproject.api.system.Clock;
 import org.briarproject.util.StringUtils;
 
@@ -37,43 +40,41 @@ public abstract class BdfMessageValidator implements MessageValidator,
 		this.clock = clock;
 	}
 
-	protected abstract BdfDictionary validateMessage(Message m, Group g,
-			BdfList body) throws FormatException;
+	protected abstract BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws InvalidMessageException, FormatException;
 
 	@Override
-	public Metadata validateMessage(Message m, Group g) {
+	public MessageContext validateMessage(Message m, Group g)
+			throws InvalidMessageException {
 		return validateMessage(m, g, MESSAGE_HEADER_LENGTH);
 	}
 
 	@Override
-	public Metadata validateMessage(QueueMessage q, Group g) {
+	public MessageContext validateMessage(QueueMessage q, Group g)
+			throws InvalidMessageException {
 		return validateMessage(q, g, QUEUE_MESSAGE_HEADER_LENGTH);
 	}
 
-	private Metadata validateMessage(Message m, Group g, int headerLength) {
+	private MessageContext validateMessage(Message m, Group g, int headerLength)
+			throws InvalidMessageException {
 		// Reject the message if it's too far in the future
 		long now = clock.currentTimeMillis();
 		if (m.getTimestamp() - now > MAX_CLOCK_DIFFERENCE) {
-			LOG.info("Timestamp is too far in the future");
-			return null;
+			throw new InvalidMessageException(
+					"Timestamp is too far in the future");
 		}
 		byte[] raw = m.getRaw();
 		if (raw.length <= headerLength) {
-			LOG.info("Message is too short");
-			return null;
+			throw new InvalidMessageException("Message is too short");
 		}
 		try {
 			BdfList body = clientHelper.toList(raw, headerLength,
 					raw.length - headerLength);
-			BdfDictionary meta = validateMessage(m, g, body);
-			if (meta == null) {
-				LOG.info("Invalid message");
-				return null;
-			}
-			return metadataEncoder.encode(meta);
+			BdfMessageContext result = validateMessage(m, g, body);
+			Metadata meta = metadataEncoder.encode(result.getDictionary());
+			return new MessageContext(meta, result.getDependencies());
 		} catch (FormatException e) {
-			LOG.info("Invalid message");
-			return null;
+			throw new InvalidMessageException(e);
 		}
 	}
 
diff --git a/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java b/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java
index 1459d7da6dbf2de84f8c4737659087c43972884e..83ede64e67e33b849b948f7f82cd68d9a9c3c592 100644
--- a/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java
+++ b/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java
@@ -14,10 +14,12 @@ import org.briarproject.api.db.Transaction;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
+import org.briarproject.api.sync.InvalidMessageException;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.api.sync.ValidationManager;
 import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
+import org.briarproject.api.sync.MessageContext;
 import org.briarproject.util.ByteUtils;
 
 import java.util.ArrayList;
@@ -169,7 +171,8 @@ class MessageQueueManagerImpl implements MessageQueueManager {
 		}
 
 		@Override
-		public Metadata validateMessage(Message m, Group g) {
+		public MessageContext validateMessage(Message m, Group g)
+				throws InvalidMessageException {
 			byte[] raw = m.getRaw();
 			if (raw.length < QUEUE_MESSAGE_HEADER_LENGTH) return null;
 			long queuePosition = ByteUtils.readUint64(raw,
diff --git a/briar-core/src/org/briarproject/forum/ForumPostValidator.java b/briar-core/src/org/briarproject/forum/ForumPostValidator.java
index 8796bb7e6d430034d3b08fefbabfe75b93fa382e..6dbc68e96f6ff5ff8a8134d1b663ba5ea5f29ed8 100644
--- a/briar-core/src/org/briarproject/forum/ForumPostValidator.java
+++ b/briar-core/src/org/briarproject/forum/ForumPostValidator.java
@@ -3,6 +3,7 @@ package org.briarproject.forum;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.UniqueId;
 import org.briarproject.api.clients.ClientHelper;
+import org.briarproject.api.clients.BdfMessageContext;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.KeyParser;
 import org.briarproject.api.crypto.PublicKey;
@@ -13,6 +14,7 @@ import org.briarproject.api.data.MetadataEncoder;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.sync.Group;
+import org.briarproject.api.sync.InvalidMessageException;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.system.Clock;
 import org.briarproject.clients.BdfMessageValidator;
@@ -39,8 +41,8 @@ class ForumPostValidator extends BdfMessageValidator {
 	}
 
 	@Override
-	protected BdfDictionary validateMessage(Message m, Group g,
-			BdfList body) throws FormatException {
+	protected BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws InvalidMessageException, FormatException {
 		// Parent ID, author, content type, forum post body, signature
 		checkSize(body, 5);
 		// Parent ID is optional
@@ -69,12 +71,10 @@ class ForumPostValidator extends BdfMessageValidator {
 		checkLength(sig, 0, MAX_SIGNATURE_LENGTH);
 		// If there's an author there must be a signature and vice versa
 		if (author != null && sig == null) {
-			LOG.info("Author without signature");
-			return null;
+			throw new InvalidMessageException("Author without signature");
 		}
 		if (author == null && sig != null) {
-			LOG.info("Signature without author");
-			return null;
+			throw new InvalidMessageException("Signature without author");
 		}
 		// Verify the signature, if any
 		if (author != null) {
@@ -90,12 +90,10 @@ class ForumPostValidator extends BdfMessageValidator {
 				signature.initVerify(key);
 				signature.update(clientHelper.toByteArray(signed));
 				if (!signature.verify(sig)) {
-					LOG.info("Invalid signature");
-					return null;
+					throw new InvalidMessageException("Invalid signature");
 				}
 			} catch (GeneralSecurityException e) {
-				LOG.info("Invalid public key");
-				return null;
+				throw new InvalidMessageException("Invalid public key");
 			}
 		}
 		// Return the metadata
@@ -111,6 +109,6 @@ class ForumPostValidator extends BdfMessageValidator {
 		}
 		meta.put("contentType", contentType);
 		meta.put("read", false);
-		return meta;
+		return new BdfMessageContext(meta);
 	}
 }
diff --git a/briar-core/src/org/briarproject/forum/ForumSharingValidator.java b/briar-core/src/org/briarproject/forum/ForumSharingValidator.java
index b162579433ad180719d24bd25b628dc3b32ea9da..5009588869a5b4c49a9242809a5a9a340e28c4a3 100644
--- a/briar-core/src/org/briarproject/forum/ForumSharingValidator.java
+++ b/briar-core/src/org/briarproject/forum/ForumSharingValidator.java
@@ -3,6 +3,7 @@ package org.briarproject.forum;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.clients.SessionId;
+import org.briarproject.api.clients.BdfMessageContext;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.MetadataEncoder;
@@ -36,7 +37,7 @@ class ForumSharingValidator extends BdfMessageValidator {
 	}
 
 	@Override
-	protected BdfDictionary validateMessage(Message m, Group g,
+	protected BdfMessageContext validateMessage(Message m, Group g,
 			BdfList body) throws FormatException {
 
 		BdfDictionary d = new BdfDictionary();
@@ -75,6 +76,6 @@ class ForumSharingValidator extends BdfMessageValidator {
 		d.put(SESSION_ID, id);
 		d.put(LOCAL, false);
 		d.put(TIME, m.getTimestamp());
-		return d;
+		return new BdfMessageContext(d);
 	}
 }
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
index 374a15b2ed1c9776424baf1a8edaf21d7e78aee3..7eacaccc839485c108841c03f2d068663e3cc7f5 100644
--- a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
+++ b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
@@ -2,10 +2,11 @@ package org.briarproject.introduction;
 
 import org.briarproject.api.FormatException;
 import org.briarproject.api.clients.ClientHelper;
+import org.briarproject.api.clients.SessionId;
+import org.briarproject.api.clients.BdfMessageContext;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.system.Clock;
@@ -42,7 +43,7 @@ class IntroductionValidator extends BdfMessageValidator {
 	}
 
 	@Override
-	protected BdfDictionary validateMessage(Message m, Group g, BdfList body)
+	protected BdfMessageContext validateMessage(Message m, Group g, BdfList body)
 			throws FormatException {
 
 		BdfDictionary d;
@@ -67,7 +68,7 @@ class IntroductionValidator extends BdfMessageValidator {
 		d.put(GROUP_ID, m.getGroupId());
 		d.put(MESSAGE_ID, m.getId());
 		d.put(MESSAGE_TIME, m.getTimestamp());
-		return d;
+		return new BdfMessageContext(d);
 	}
 
 	private BdfDictionary validateRequest(BdfList message)
diff --git a/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java b/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java
index 550da3f9c77d7ab8eaebc9365105275a35cb23af..74bd0d904e65c3e1b28858cdda066994d14a27b2 100644
--- a/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java
+++ b/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java
@@ -3,6 +3,7 @@ package org.briarproject.messaging;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.UniqueId;
 import org.briarproject.api.clients.ClientHelper;
+import org.briarproject.api.clients.BdfMessageContext;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.MetadataEncoder;
@@ -22,7 +23,7 @@ class PrivateMessageValidator extends BdfMessageValidator {
 	}
 
 	@Override
-	protected BdfDictionary validateMessage(Message m, Group g,
+	protected BdfMessageContext validateMessage(Message m, Group g,
 			BdfList body) throws FormatException {
 		// Parent ID, content type, private message body
 		checkSize(body, 3);
@@ -42,6 +43,6 @@ class PrivateMessageValidator extends BdfMessageValidator {
 		meta.put("contentType", contentType);
 		meta.put("local", false);
 		meta.put("read", false);
-		return meta;
+		return new BdfMessageContext(meta);
 	}
 }
diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java b/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java
index fc40dd342a65ccc619fc7071119590270a66c6e4..940c6b0f1c955eee2152fc3b5f1e0afb133a559e 100644
--- a/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java
+++ b/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java
@@ -2,6 +2,7 @@ package org.briarproject.properties;
 
 import org.briarproject.api.FormatException;
 import org.briarproject.api.clients.ClientHelper;
+import org.briarproject.api.clients.BdfMessageContext;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.MetadataEncoder;
@@ -22,7 +23,7 @@ public class TransportPropertyValidator extends BdfMessageValidator {
 	}
 
 	@Override
-	protected BdfDictionary validateMessage(Message m, Group g,
+	protected BdfMessageContext validateMessage(Message m, Group g,
 			BdfList body) throws FormatException {
 		// Transport ID, version, properties
 		checkSize(body, 3);
@@ -45,6 +46,6 @@ public class TransportPropertyValidator extends BdfMessageValidator {
 		meta.put("transportId", transportId);
 		meta.put("version", version);
 		meta.put("local", false);
-		return meta;
+		return new BdfMessageContext(meta);
 	}
 }
diff --git a/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java b/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java
index 52121c706aae350a94cb8fbddd28597127278667..1e85803a22aba9d836f5564b23b3fb8854f10917 100644
--- a/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java
+++ b/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java
@@ -16,9 +16,11 @@ import org.briarproject.api.lifecycle.Service;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
+import org.briarproject.api.sync.InvalidMessageException;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.api.sync.ValidationManager;
+import org.briarproject.api.sync.MessageContext;
 import org.briarproject.util.ByteUtils;
 
 import java.util.LinkedList;
@@ -31,6 +33,7 @@ import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
+import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
@@ -152,31 +155,54 @@ class ValidationManagerImpl implements ValidationManager, Service,
 				if (v == null) {
 					LOG.warning("No validator");
 				} else {
-					Metadata meta = v.validateMessage(m, g);
-					storeValidationResult(m, g.getClientId(), meta);
+					try {
+						MessageContext context = v.validateMessage(m, g);
+						storeMessageContext(m, g.getClientId(), context);
+					} catch (InvalidMessageException e) {
+						if (LOG.isLoggable(INFO))
+							LOG.log(INFO, e.toString(), e);
+						markMessageInvalid(m, g.getClientId());
+					}
+				}
+			}
+		});
+	}
+
+	private void storeMessageContext(final Message m, final ClientId c,
+			final MessageContext result) {
+		dbExecutor.execute(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					Transaction txn = db.startTransaction(false);
+					try {
+						Metadata meta = result.getMetadata();
+						db.mergeMessageMetadata(txn, m.getId(), meta);
+						db.setMessageValid(txn, m, c, true);
+						db.setMessageShared(txn, m, true);
+						IncomingMessageHook hook = hooks.get(c);
+						if (hook != null)
+							hook.incomingMessage(txn, m, meta);
+						txn.setComplete();
+					} finally {
+						db.endTransaction(txn);
+					}
+				} catch (DbException e) {
+					if (LOG.isLoggable(WARNING))
+						LOG.log(WARNING, e.toString(), e);
 				}
 			}
 		});
 	}
 
-	private void storeValidationResult(final Message m, final ClientId c,
-			final Metadata meta) {
+	private void markMessageInvalid(final Message m, final ClientId c) {
 		dbExecutor.execute(new Runnable() {
 			@Override
 			public void run() {
 				try {
 					Transaction txn = db.startTransaction(false);
 					try {
-						if (meta == null) {
-							db.setMessageValid(txn, m, c, false);
-						} else {
-							db.mergeMessageMetadata(txn, m.getId(), meta);
-							db.setMessageValid(txn, m, c, true);
-							db.setMessageShared(txn, m, true);
-							IncomingMessageHook hook = hooks.get(c);
-							if (hook != null)
-								hook.incomingMessage(txn, m, meta);
-						}
+						db.setMessageValid(txn, m, c, false);
 						txn.setComplete();
 					} finally {
 						db.endTransaction(txn);
diff --git a/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java b/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java
index 05ca7fa32e1f21ed1940315b58171e8e2805243e..0daa229964e1569ea53f2c57e08d6cc5fa4d64e1 100644
--- a/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java
@@ -20,6 +20,7 @@ import org.briarproject.api.sync.MessageId;
 import org.briarproject.api.sync.ValidationManager;
 import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
 import org.briarproject.api.sync.ValidationManager.MessageValidator;
+import org.briarproject.api.sync.MessageContext;
 import org.briarproject.util.ByteUtils;
 import org.hamcrest.Description;
 import org.jmock.Expectations;
@@ -210,7 +211,9 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
 				new AtomicReference<MessageValidator>();
 		final QueueMessageValidator queueMessageValidator =
 				context.mock(QueueMessageValidator.class);
-		final Metadata messageMetadata = new Metadata();
+		final Metadata metadata = new Metadata();
+		final MessageContext messageContext =
+				new MessageContext(metadata);
 		// The message is valid, with a queue position of zero
 		final MessageId messageId = new MessageId(TestUtils.getRandomId());
 		final byte[] raw = new byte[QUEUE_MESSAGE_HEADER_LENGTH];
@@ -224,7 +227,7 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
 			// The message should be delegated
 			oneOf(queueMessageValidator).validateMessage(
 					with(any(QueueMessage.class)), with(group));
-			will(returnValue(messageMetadata));
+			will(returnValue(messageContext));
 		}});
 
 		MessageQueueManagerImpl mqm = new MessageQueueManagerImpl(db,
@@ -235,7 +238,8 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
 		MessageValidator delegate = captured.get();
 		assertNotNull(delegate);
 		// The message should be valid and the metadata should be returned
-		assertSame(messageMetadata, delegate.validateMessage(message, group));
+		assertSame(messageContext, delegate.validateMessage(message, group));
+		assertSame(metadata, messageContext.getMetadata());
 
 		context.assertIsSatisfied();
 	}
diff --git a/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java b/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
index d7d4112946dcce2965d76a7bcf29519630020e6e..5399abdbcaf9033663549b5080aa6637d79c607e 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
+++ b/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
@@ -85,7 +85,8 @@ public class IntroductionValidatorTest extends BriarTestCase {
 				name, publicKey, text);
 
 		final BdfDictionary result =
-				validator.validateMessage(message, group, body);
+				validator.validateMessage(message, group, body)
+						.getDictionary();
 
 		assertEquals(Long.valueOf(TYPE_REQUEST), result.getLong(TYPE));
 		assertEquals(sessionId, result.getRaw(SESSION_ID));
@@ -182,7 +183,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
 				msg.getRaw(E_PUBLIC_KEY), msg.getDictionary(TRANSPORT));
 
 		final BdfDictionary result =
-				validator.validateMessage(message, group, body);
+				validator.validateMessage(message, group, body).getDictionary();
 
 		assertEquals(Long.valueOf(TYPE_RESPONSE), result.getLong(TYPE));
 		assertEquals(sessionId, result.getRaw(SESSION_ID));
@@ -199,7 +200,8 @@ public class IntroductionValidatorTest extends BriarTestCase {
 		BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
 				msg.getBoolean(ACCEPT));
 
-		BdfDictionary result = validator.validateMessage(message, group, body);
+		BdfDictionary result = validator.validateMessage(message, group, body)
+				.getDictionary();
 
 		assertFalse(result.getBoolean(ACCEPT));
 		context.assertIsSatisfied();
@@ -288,7 +290,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
 		BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID));
 
 		BdfDictionary result =
-				validator.validateMessage(message, group, body);
+				validator.validateMessage(message, group, body).getDictionary();
 
 		assertEquals(Long.valueOf(TYPE_ACK), result.getLong(TYPE));
 		assertEquals(sessionId, result.getRaw(SESSION_ID));
@@ -334,7 +336,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
 		BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID));
 
 		BdfDictionary result =
-				validator.validateMessage(message, group, body);
+				validator.validateMessage(message, group, body).getDictionary();
 
 		assertEquals(Long.valueOf(TYPE_ABORT), result.getLong(TYPE));
 		assertEquals(sessionId, result.getRaw(SESSION_ID));
diff --git a/briar-tests/src/org/briarproject/properties/TransportPropertyValidatorTest.java b/briar-tests/src/org/briarproject/properties/TransportPropertyValidatorTest.java
index bc61508117b31fcb0a4425022c4122f5d50e3614..f719479f166422ae1466aa997f7a32a9479ef3a0 100644
--- a/briar-tests/src/org/briarproject/properties/TransportPropertyValidatorTest.java
+++ b/briar-tests/src/org/briarproject/properties/TransportPropertyValidatorTest.java
@@ -59,7 +59,8 @@ public class TransportPropertyValidatorTest extends BriarTestCase {
 
 		BdfList body = BdfList.of(transportId.getString(), 4, bdfDictionary);
 
-		BdfDictionary result = tpv.validateMessage(message, group, body);
+		BdfDictionary result = tpv.validateMessage(message, group, body)
+				.getDictionary();
 
 		assertEquals("test", result.getString("transportId"));
 		assertEquals(4, result.getLong("version").longValue());
diff --git a/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java b/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java
index 9a5ec0dd3866b5bc9720a201fb4787ebfe7e5c76..1aea2e30b01fea7a8db15b210a8fb1fc5a77a345 100644
--- a/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java
@@ -14,10 +14,12 @@ import org.briarproject.api.event.MessageAddedEvent;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
+import org.briarproject.api.sync.InvalidMessageException;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
 import org.briarproject.api.sync.ValidationManager.MessageValidator;
+import org.briarproject.api.sync.MessageContext;
 import org.briarproject.util.ByteUtils;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -41,6 +43,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
 	private final Message message1 = new Message(messageId1, groupId, timestamp,
 			raw);
 	private final Metadata metadata = new Metadata();
+	final MessageContext validResult = new MessageContext(metadata);
 	private final ContactId contactId = new ContactId(234);
 
 	public ValidationManagerImplTest() {
@@ -80,7 +83,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
 			oneOf(db).endTransaction(txn1);
 			// Validate the first message: valid
 			oneOf(validator).validateMessage(message, group);
-			will(returnValue(metadata));
+			will(returnValue(validResult));
 			// Store the validation result for the first message
 			oneOf(db).startTransaction(false);
 			will(returnValue(txn2));
@@ -100,7 +103,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
 			oneOf(db).endTransaction(txn3);
 			// Validate the second message: invalid
 			oneOf(validator).validateMessage(message1, group);
-			will(returnValue(null));
+			will(throwException(new InvalidMessageException()));
 			// Store the validation result for the second message
 			oneOf(db).startTransaction(false);
 			will(returnValue(txn4));
@@ -154,7 +157,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
 			oneOf(db).endTransaction(txn2);
 			// Validate the second message: invalid
 			oneOf(validator).validateMessage(message1, group);
-			will(returnValue(null));
+			will(throwException(new InvalidMessageException()));
 			// Store the validation result for the second message
 			oneOf(db).startTransaction(false);
 			will(returnValue(txn3));
@@ -211,7 +214,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
 			oneOf(db).endTransaction(txn2);
 			// Validate the second message: invalid
 			oneOf(validator).validateMessage(message1, group);
-			will(returnValue(null));
+			will(throwException(new InvalidMessageException()));
 			// Store the validation result for the second message
 			oneOf(db).startTransaction(false);
 			will(returnValue(txn3));
@@ -248,7 +251,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
 			oneOf(db).endTransaction(txn);
 			// Validate the message: valid
 			oneOf(validator).validateMessage(message, group);
-			will(returnValue(metadata));
+			will(returnValue(validResult));
 			// Store the validation result
 			oneOf(db).startTransaction(false);
 			will(returnValue(txn1));