diff --git a/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java b/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java
index 993af1b6e9dd13c815d95f2ef2e6006543631165..1ea9c17b575e08147e7de120c6190a5d5be9c50f 100644
--- a/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java
+++ b/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java
@@ -69,8 +69,11 @@ public interface DatabaseComponent {
 	 */
 	void addSecrets(Collection<TemporarySecret> secrets) throws DbException;
 
-	/** Adds a transport to the database. */
-	void addTransport(TransportId t) throws DbException;
+	/**
+	 * Adds a transport to the database and returns true if the transport was
+	 * not previously in the database.
+	 */
+	boolean addTransport(TransportId t) throws DbException;
 
 	/**
 	 * Generates an acknowledgement for the given contact. Returns null if
diff --git a/briar-core/src/net/sf/briar/db/Database.java b/briar-core/src/net/sf/briar/db/Database.java
index dfc9d00d7809f6d4ff85c63b1c6a04ced20c7c89..209c40722df549242a0872766212f7d22b0db66d 100644
--- a/briar-core/src/net/sf/briar/db/Database.java
+++ b/briar-core/src/net/sf/briar/db/Database.java
@@ -140,11 +140,12 @@ interface Database<T> {
 	boolean addSubscription(T txn, Group g) throws DbException;
 
 	/**
-	 * Adds a new transport to the database.
+	 * Adds a new transport to the database and returns true if the transport
+	 * was not previously in the database.
 	 * <p>
 	 * Locking: transport write.
 	 */
-	void addTransport(T txn, TransportId t) throws DbException;
+	boolean addTransport(T txn, TransportId t) throws DbException;
 
 	/**
 	 * Makes the given group visible to the given contact.
diff --git a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
index e18601d06d3fc1f223c17a61e0ee7feb5d290edc..b27f8acc754a3fe97cefa533992995c08af246f7 100644
--- a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
@@ -349,7 +349,7 @@ DatabaseCleaner.Callback {
 
 	public void addLocalPrivateMessage(Message m, ContactId c)
 			throws DbException {
-		boolean added = false;
+		boolean added;
 		contactLock.readLock().lock();
 		try {
 			messageLock.writeLock().lock();
@@ -409,12 +409,13 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public void addTransport(TransportId t) throws DbException {
+	public boolean addTransport(TransportId t) throws DbException {
+		boolean added;
 		transportLock.writeLock().lock();
 		try {
 			T txn = db.startTransaction();
 			try {
-				db.addTransport(txn, t);
+				added = db.addTransport(txn, t);
 				db.commitTransaction(txn);
 			} catch(DbException e) {
 				db.abortTransaction(txn);
@@ -423,7 +424,8 @@ DatabaseCleaner.Callback {
 		} finally {
 			transportLock.writeLock().unlock();
 		}
-		callListeners(new TransportAddedEvent(t));
+		if(added) callListeners(new TransportAddedEvent(t));
+		return added;
 	}
 
 	/**
@@ -1845,8 +1847,4 @@ DatabaseCleaner.Callback {
 		}
 		return false;
 	}
-
-	public void rotateKeys() throws DbException {
-
-	}
 }
diff --git a/briar-core/src/net/sf/briar/db/JdbcDatabase.java b/briar-core/src/net/sf/briar/db/JdbcDatabase.java
index 78d5adfe279c869986854a4edacbafb8e1795d9c..550b20e4406d818a1ee45fc1b36706a7a9171c4c 100644
--- a/briar-core/src/net/sf/briar/db/JdbcDatabase.java
+++ b/briar-core/src/net/sf/briar/db/JdbcDatabase.java
@@ -788,12 +788,23 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public void addTransport(Connection txn, TransportId t) throws DbException {
+	public boolean addTransport(Connection txn, TransportId t)
+			throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
+			// Return false if the transport is already in the database
+			String sql = "SELECT NULL FROM transports WHERE transportId = ?";
+			ps = txn.prepareStatement(sql);
+			ps.setBytes(1, t.getBytes());
+			rs = ps.executeQuery();
+			boolean found = rs.next();
+			if(rs.next()) throw new DbStateException();
+			rs.close();
+			ps.close();
+			if(found) return false;
 			// Create a transport row
-			String sql = "INSERT INTO transports (transportId) VALUES (?)";
+			sql = "INSERT INTO transports (transportId) VALUES (?)";
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, t.getBytes());
 			int affected = ps.executeUpdate();
@@ -807,7 +818,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			while(rs.next()) contacts.add(rs.getInt(1));
 			rs.close();
 			ps.close();
-			if(contacts.isEmpty()) return;
+			if(contacts.isEmpty()) return true;
 			sql = "INSERT INTO transportVersions (contactId, transportId,"
 					+ " localVersion, localAcked, expiry, txCount)"
 					+ " VALUES (?, ?, ?, ZERO(), ZERO(), ZERO())";
@@ -824,6 +835,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			for(int i = 0; i < batchAffected.length; i++) {
 				if(batchAffected[i] != 1) throw new DbStateException();
 			}
+			return true;
 		} catch(SQLException e) {
 			tryToClose(ps);
 			tryToClose(rs);
diff --git a/briar-core/src/net/sf/briar/plugins/PluginManagerImpl.java b/briar-core/src/net/sf/briar/plugins/PluginManagerImpl.java
index c11c4fcd6e13ec323c21bf4f3fe4575c869c13f2..902fbbd9c63db2b814133ae8f8fb4feba8bdc233 100644
--- a/briar-core/src/net/sf/briar/plugins/PluginManagerImpl.java
+++ b/briar-core/src/net/sf/briar/plugins/PluginManagerImpl.java
@@ -88,6 +88,12 @@ class PluginManagerImpl implements PluginManager {
 					LOG.warning("Duplicate transport ID: " + id);
 				continue;
 			}
+			try {
+				db.addTransport(id);
+			} catch(DbException e) {
+				if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+				continue;
+			}
 			SimplexCallback callback = new SimplexCallback(id);
 			SimplexPlugin plugin = factory.createPlugin(callback);
 			if(plugin == null) {
@@ -118,6 +124,12 @@ class PluginManagerImpl implements PluginManager {
 					LOG.warning("Duplicate transport ID: " + id);
 				continue;
 			}
+			try {
+				db.addTransport(id);
+			} catch(DbException e) {
+				if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+				continue;
+			}
 			DuplexCallback callback = new DuplexCallback(id);
 			DuplexPlugin plugin = factory.createPlugin(callback);
 			if(plugin == null) {
diff --git a/briar-tests/src/net/sf/briar/plugins/PluginManagerImplTest.java b/briar-tests/src/net/sf/briar/plugins/PluginManagerImplTest.java
index a080b890d6f300d95cf8eca1561e2a561eb8ca65..cd610cb1e6c3bfbee06cc287dbe270fd2ed1fac3 100644
--- a/briar-tests/src/net/sf/briar/plugins/PluginManagerImplTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/PluginManagerImplTest.java
@@ -54,6 +54,8 @@ public class PluginManagerImplTest extends BriarTestCase {
 			will(returnValue(Arrays.asList(removableDrive)));
 			oneOf(duplexPluginConfig).getFactories();
 			will(returnValue(Arrays.asList(lanTcp)));
+			exactly(2).of(db).addTransport(with(any(TransportId.class)));
+			will(returnValue(true));
 			oneOf(poller).start(with(any(Collection.class)));
 			allowing(db).getConfig(with(any(TransportId.class)));
 			will(returnValue(new TransportConfig()));