diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java
index e8b2288fb6c4c485d55525981360a9a497dbeb55..ec2582ff080be9643533856023158382c63ccbc7 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java
@@ -131,9 +131,18 @@ public class OlmSessionTest {
         assertTrue(0!=aliceSession.getOlmSessionId());
 
         // CREATE ALICE OUTBOUND SESSION and encrypt message to bob
-        assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey));
+        try {
+            aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         String clearMsg = "Heloo bob , this is alice!";
-        OlmMessage encryptedMsgToBob = aliceSession.encryptMessage(clearMsg);
+        OlmMessage encryptedMsgToBob = null;
+        try {
+            encryptedMsgToBob = aliceSession.encryptMessage(clearMsg);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsgToBob);
         assertNotNull(encryptedMsgToBob.mCipherText);
         Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText);
@@ -153,7 +162,12 @@ public class OlmSessionTest {
             assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false);
         }
 
-        String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob);
+        String decryptedMsg = null;
+        try {
+            decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(decryptedMsg);
 
         // MESSAGE COMPARISON: decrypted vs encrypted
@@ -255,10 +269,22 @@ public class OlmSessionTest {
         assertTrue(0!=aliceSession.getOlmSessionId());
 
         // CREATE ALICE OUTBOUND SESSION and encrypt message to bob
-        assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey));
+        try {
+            aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         String helloClearMsg = "Hello I'm Alice!";
 
-        OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg);
+        OlmMessage encryptedAliceToBobMsg1 = null;
+
+        try {
+            encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         assertNotNull(encryptedAliceToBobMsg1);
         assertNotNull(encryptedAliceToBobMsg1.mCipherText);
 
@@ -279,7 +305,12 @@ public class OlmSessionTest {
         }
 
         // DECRYPT MESSAGE FROM ALICE
-        String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1);
+        String decryptedMsg01 = null;
+        try {
+            decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(decryptedMsg01);
 
         // MESSAGE COMPARISON: decrypted vs encrypted
@@ -291,19 +322,54 @@ public class OlmSessionTest {
         String clearMsg3 = "Let's go to the opera.";
 
         // bob encrypts messages
-        OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1);
+        OlmMessage encryptedMsg1 = null;
+        try {
+            encryptedMsg1 = bobSession.encryptMessage(clearMsg1);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsg1);
-        OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2);
+
+        OlmMessage encryptedMsg2 = null;
+        try {
+            encryptedMsg2 = bobSession.encryptMessage(clearMsg2);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsg2);
-        OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3);
+
+
+        OlmMessage encryptedMsg3 = null;
+        try {
+            encryptedMsg3 = bobSession.encryptMessage(clearMsg3);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsg3);
 
         // alice decrypts bob's messages
-        String decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1);
+        String decryptedMsg1 = null;
+        try {
+            decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         assertNotNull(decryptedMsg1);
-        String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2);
+        String decryptedMsg2 = null;
+        try {
+            decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         assertNotNull(decryptedMsg2);
-        String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3);
+        String decryptedMsg3 = null;
+        try {
+            decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(decryptedMsg3);
 
         // comparison tests
@@ -313,9 +379,22 @@ public class OlmSessionTest {
 
         // and one more from alice to bob
         clearMsg1 = "another message from Alice to Bob!!";
-        encryptedMsg1 = aliceSession.encryptMessage(clearMsg1);
+        encryptedMsg1 = null;
+
+        try {
+            encryptedMsg1 = aliceSession.encryptMessage(clearMsg1);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsg1);
-        decryptedMsg1 = bobSession.decryptMessage(encryptedMsg1);
+
+        decryptedMsg1 = null;
+        try {
+            decryptedMsg1 = bobSession.decryptMessage(encryptedMsg1);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         assertNotNull(decryptedMsg1);
         assertTrue(clearMsg1.equals(decryptedMsg1));
 
@@ -378,10 +457,21 @@ public class OlmSessionTest {
         }
         assertTrue(0!=bobSession.getOlmSessionId());
 
-        String aliceSessionId = aliceSession.sessionIdentifier();
+        String aliceSessionId = null;
+        try {
+            aliceSessionId = aliceSession.sessionIdentifier();
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         assertNotNull(aliceSessionId);
 
-        String bobSessionId = bobSession.sessionIdentifier();
+        String bobSessionId = null;
+        try {
+            bobSessionId = bobSession.sessionIdentifier();
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(bobSessionId);
 
         // must be the same for both ends of the conversation
@@ -463,10 +553,21 @@ public class OlmSessionTest {
         String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeys, 1);
 
         // create alice inbound session for bob
-        assertTrue(0==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey1));
+        try {
+            aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey1);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
 
         String aliceClearMsg = "hello helooo to bob!";
-        OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg);
+        OlmMessage encryptedAliceToBobMsg1 = null;
+
+        try {
+            encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         assertFalse(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText));
 
         // init bob session with alice PRE KEY
@@ -571,10 +672,20 @@ public class OlmSessionTest {
         assertTrue(0!=aliceSession.getOlmSessionId());
 
         // CREATE ALICE OUTBOUND SESSION and encrypt message to bob
-        assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey));
+        try {
+            aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         String helloClearMsg = "Hello I'm Alice!";
 
-        OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg);
+        OlmMessage encryptedAliceToBobMsg1 = null;
+        try {
+            encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedAliceToBobMsg1);
         assertNotNull(encryptedAliceToBobMsg1.mCipherText);
 
@@ -595,7 +706,14 @@ public class OlmSessionTest {
         }
 
         // DECRYPT MESSAGE FROM ALICE
-        String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1);
+        String decryptedMsg01 = null;
+
+        try {
+            decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         assertNotNull(decryptedMsg01);
 
         // MESSAGE COMPARISON: decrypted vs encrypted
@@ -607,11 +725,28 @@ public class OlmSessionTest {
         String clearMsg3 = "Let's go to the opera.";
 
         // bob encrypts messages
-        OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1);
+        OlmMessage encryptedMsg1 = null;
+        try {
+            encryptedMsg1 = bobSession.encryptMessage(clearMsg1);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsg1);
-        OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2);
+
+        OlmMessage encryptedMsg2 = null;
+        try {
+            encryptedMsg2 = bobSession.encryptMessage(clearMsg2);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsg2);
-        OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3);
+
+        OlmMessage encryptedMsg3 = null;
+        try {
+            encryptedMsg3 = bobSession.encryptMessage(clearMsg3);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsg3);
 
         // serialize alice session
@@ -742,26 +877,70 @@ public class OlmSessionTest {
         }
 
         // SANITY CHECK TESTS FOR: initOutboundSessionWithAccount()
-        assertTrue(-1==aliceSession.initOutboundSession(null, bobIdentityKey, bobOneTimeKey));
-        assertTrue(-1==aliceSession.initOutboundSession(aliceAccount, null, bobOneTimeKey));
-        assertTrue(-1==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, null));
-        assertTrue(-1==aliceSession.initOutboundSession(null, null, null));
+        String errorMessage = null;
+        try {
+            aliceSession.initOutboundSession(null, bobIdentityKey, bobOneTimeKey);
+        } catch (Exception e) {
+            errorMessage = e.getMessage();
+        }
+        assertTrue(null != errorMessage);
+
+        errorMessage = null;
+        try {
+            aliceSession.initOutboundSession(aliceAccount, null, bobOneTimeKey);
+        } catch (Exception e) {
+            errorMessage = e.getMessage();
+        }
+        assertTrue(null != errorMessage);
+
+        errorMessage = null;
+        try {
+            aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, null);
+        } catch (Exception e) {
+            errorMessage = e.getMessage();
+        }
+        assertTrue(null != errorMessage);
+
+        errorMessage = null;
+        try {
+            aliceSession.initOutboundSession(null, null, null);
+        } catch (Exception e) {
+            errorMessage = e.getMessage();
+        }
+        assertTrue(null != errorMessage);
 
         // init properly
-        assertTrue(0==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey));
+        errorMessage = null;
+        try {
+            aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey);
+        } catch (Exception e) {
+            errorMessage = e.getMessage();
+        }
+        assertTrue(null == errorMessage);
 
         // SANITY CHECK TESTS FOR: encryptMessage()
-        assertTrue(null==aliceSession.encryptMessage(null));
+        OlmMessage message = null;
+        try {
+            message = aliceSession.encryptMessage(null);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+        assertTrue(null==message);
 
         // encrypt properly
-        OlmMessage encryptedMsgToBob = aliceSession.encryptMessage("A message for bob");
+        OlmMessage encryptedMsgToBob = null;
+        try {
+            encryptedMsgToBob = aliceSession.encryptMessage("A message for bob");
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
         assertNotNull(encryptedMsgToBob);
 
         // SANITY CHECK TESTS FOR: initInboundSessionWithAccount()
         OlmSession bobSession = null;
         try {
             bobSession = new OlmSession();
-            String errorMessage = null;
+            errorMessage = null;
             try {
                 bobSession.initInboundSession(null, encryptedMsgToBob.mCipherText);
             } catch (Exception e) {
@@ -802,7 +981,13 @@ public class OlmSessionTest {
         }
 
         // SANITY CHECK TESTS FOR: decryptMessage()
-        String decryptedMsg = aliceSession.decryptMessage(null);
+        String decryptedMsg = null;
+        try {
+            decryptedMsg = aliceSession.decryptMessage(null);
+        } catch (Exception e) {
+            assertTrue(e.getMessage(), false);
+        }
+
         assertTrue(null==decryptedMsg);
 
         // SANITY CHECK TESTS FOR: matchesInboundSession()
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java
index 1a1b8abc65de0b94cee65d785595df886a150f8e..a6f18051bd47de538480b8d96e32b48baebb6594 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java
@@ -24,41 +24,40 @@ import java.io.IOException;
  */
 public class OlmException extends IOException {
     // exception codes
-    public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 0;
-    public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 1;
-    public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 2;
-    public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 3;
-    public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 4;
-    public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 5;
-    public static final int EXCEPTION_CODE_SESSION_SERIALIZATION = 6;
-    public static final int EXCEPTION_CODE_SESSION_DESERIALIZATION = 7;
-    public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 8;
-    public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 9;
-    public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_SERIALIZATION = 10;
-    public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION = 11;
-    public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_SERIALIZATION = 12;
-    public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION = 13;
 
-    public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 20;
-    public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 21;
-    public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 22;
-    public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 23;
-    public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 24;
-    public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 25;
+    public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 10;
 
-    public static final int EXCEPTION_CODE_SESSION_IDENTIFIER = 30;
-    public static final int EXCEPTION_CODE_SESSION_DECRYPT_SESSION = 31;
+    public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 20;
+    public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 21;
+    public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 22;
+    public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 23;
+    public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 24;
+    public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 25;
+    public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 26;
+    public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 27;
 
-    public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 40;
-    public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 41;
-    public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 42;
+    public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 30;
+    public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 31;
+    public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER = 32;
+    public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION = 33;
+
+    public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 40;
+    public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 41;
+    public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 42;
+    public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 43;
+    public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 44;
+
+    public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 50;
+    public static final int EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION = 51;
+    public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION = 52;
+    public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM = 53;
+    public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 54;
+    public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 55;
+    public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 56;
 
     // exception human readable messages
     public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "createNewSession() failed";
     public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "createNewSession() failed";
-    public static final String EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION = "initOutboundGroupSession() failed";
-    public static final String EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION = " initInboundGroupSessionWithSessionKey() failed";
-    public static final String EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION = "initNewAccount() failure";
     public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid de-serialized parameters";
     public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "initNewAccount() failed";
     public static final String EXCEPTION_MSG_INIT_SESSION_CREATION = "initNewSession() failed";
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
index 7ac38b23528f2a1087aae0b1d5092946060cf2a7..41eeba1658f29dd7b47520f70b9535fe3c9165dd 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
@@ -141,7 +141,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
             return new String(sessionIdentifierJni(), "UTF-8");
         } catch (Exception e) {
             Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage());
-            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_IDENTIFIER, e.getMessage());
+            throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER, e.getMessage());
         }
     }
 
@@ -165,7 +165,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
             }
         } catch (Exception e) {
             Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage());
-            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_SESSION, e.getMessage());
+            throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION, e.getMessage());
         }
 
         return result;
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
index 36a95a15ea13edd10a678ccd914ff53dc9e24838..913830981091fd95fe5e1d118f20223d9f0a8b66 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
@@ -124,25 +124,23 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
      * @param aAccount the account to associate with this session
      * @param aTheirIdentityKey the identity key of the recipient
      * @param aTheirOneTimeKey the one time key of the recipient
-     * @return 0 if operation succeed, -1 otherwise
+     * @exception OlmException the failure reason
      */
-    public int initOutboundSession(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) {
-        int retCode=-1;
-
+    public void initOutboundSession(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) throws OlmException {
         if ((null == aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)) {
             Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters");
+            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION, "invalid input parameters");
         } else {
             try {
-                retCode = initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aTheirOneTimeKey.getBytes("UTF-8"));
+                initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aTheirOneTimeKey.getBytes("UTF-8"));
             } catch (Exception e) {
                 Log.e(LOG_TAG, "## initOutboundSession(): " + e.getMessage());
+                throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION, e.getMessage());
             }
         }
-
-        return retCode;
     }
 
-    private native int initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey);
+    private native void initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey);
 
     /**
      * Create a new in-bound session for sending/receiving messages from an
@@ -150,29 +148,23 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
      * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY).
      * @param aAccount the account to associate with this session
      * @param aPreKeyMsg PRE KEY message
-     * @exception Exception the failure reason
+     * @exception OlmException the failure reason
      */
-    public void initInboundSession(OlmAccount aAccount, String aPreKeyMsg) throws Exception {
+    public void initInboundSession(OlmAccount aAccount, String aPreKeyMsg) throws OlmException {
         if ((null == aAccount) || TextUtils.isEmpty(aPreKeyMsg)){
             Log.e(LOG_TAG, "## initInboundSession(): invalid input parameters");
-            throw new Exception("invalid input parameters");
+            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION, "invalid input parameters");
         } else {
-            StringBuffer errorMsg = new StringBuffer();
-
             try {
-                initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8"), errorMsg);
+                initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8"));
             } catch (Exception e) {
                 Log.e(LOG_TAG, "## initInboundSession(): " + e.getMessage());
-                errorMsg.append(errorMsg);
-            }
-
-            if (errorMsg.length() != 0) {
-                throw new Exception(errorMsg.toString());
+                throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION, e.getMessage());
             }
         }
     }
 
-    private native int initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg, StringBuffer aErrorMsg);
+    private native void initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg);
 
     /**
      * Create a new in-bound session for sending/receiving messages from an
@@ -183,38 +175,42 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
      * @param aAccount the account to associate with this session
      * @param aTheirIdentityKey the sender identity key
      * @param aPreKeyMsg PRE KEY message
-     * @return 0 if operation succeed, -1 otherwise
+     * @exception OlmException the failure reason
      */
-    public int initInboundSessionFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) {
-        int retCode=-1;
-
-        if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){
+    public void initInboundSessionFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) throws OlmException {
+        if ( (null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){
             Log.e(LOG_TAG, "## initInboundSessionFrom(): invalid input parameters");
+            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM, "invalid input parameters");
         } else {
             try {
-                retCode = initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aPreKeyMsg.getBytes("UTF-8"));
+                initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aPreKeyMsg.getBytes("UTF-8"));
             } catch (Exception e) {
                 Log.e(LOG_TAG, "## initInboundSessionFrom(): " + e.getMessage());
+                throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM, e.getMessage());
             }
         }
-
-        return retCode;
     }
 
-    private native int initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg);
+    private native void initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg);
 
     /**
      * Get the session identifier.<br> Will be the same for both ends of the
      * conversation. The session identifier is returned as a String object.
      * Session Id sample: "session_id":"M4fOVwD6AABrkTKl"
      * Public API for {@link #getSessionIdentifierJni()}.
-     * @return the session ID as a String if operation succeed, null otherwise
+     * @return the session ID
+     * @exception OlmException the failure reason
      */
-    public String sessionIdentifier() {
+    public String sessionIdentifier() throws OlmException {
         try {
-            return new String(getSessionIdentifierJni(), "UTF-8");
+            byte[] buffer = getSessionIdentifierJni();
+
+            if (null != buffer) {
+                return new String(buffer, "UTF-8");
+            }
         } catch (Exception e) {
             Log.e(LOG_TAG, "## sessionIdentifier(): " + e.getMessage());
+            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER, e.getMessage());
         }
 
         return null;
@@ -272,39 +268,46 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
      * The encrypted message is returned in a OlmMessage object.
      * Public API for {@link #encryptMessageJni(byte[], OlmMessage)}.
      * @param aClearMsg message to encrypted
-     * @return the encrypted message if operation succeed, null otherwise
+     * @return the encrypted message
+     * @exception OlmException the failure reason
      */
-    public OlmMessage encryptMessage(String aClearMsg) {
+    public OlmMessage encryptMessage(String aClearMsg) throws OlmException {
+        if (null == aClearMsg) {
+            return null;
+        }
+
         OlmMessage encryptedMsgRetValue = new OlmMessage();
 
         try {
-            if (0 != encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue)) {
-                encryptedMsgRetValue = null;
-            }
+            encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue);
         } catch (Exception e) {
             Log.e(LOG_TAG, "## encryptMessage(): failed " + e.getMessage());
-            encryptedMsgRetValue = null;
+            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE, e.getMessage());
         }
 
         return encryptedMsgRetValue;
     }
 
-    private native int encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg);
+    private native void encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg);
 
     /**
      * Decrypt a message using the session.<br>
      * The encrypted message is given as a OlmMessage object.
      * @param aEncryptedMsg message to decrypt
-     * @return the decrypted message if operation succeed, null otherwise
+     * @return the decrypted message
+     * @exception OlmException the failure reason
      */
-    public String decryptMessage(OlmMessage aEncryptedMsg) {
+    public String decryptMessage(OlmMessage aEncryptedMsg) throws OlmException {
+        if (null == aEncryptedMsg) {
+            return null;
+        }
+
         try {
             return new String(decryptMessageJni(aEncryptedMsg), "UTF-8");
         } catch (Exception e) {
             Log.e(LOG_TAG, "## decryptMessage(): failed " + e.getMessage());
+            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE, e.getMessage());
         }
-
-        return null;
     }
 
     private native byte[] decryptMessageJni(OlmMessage aEncryptedMsg);
@@ -353,7 +356,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
         } else {
             aErrorMsg.setLength(0);
             try {
-                pickleRetValue = serializeJni(aKey.getBytes("UTF-8"), aErrorMsg);
+                pickleRetValue = serializeJni(aKey.getBytes("UTF-8"));
             } catch (Exception e) {
                 Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage());
                 aErrorMsg.append(e.getMessage());
@@ -362,7 +365,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
 
         return pickleRetValue;
     }
-    private native String serializeJni(byte[] aKey, StringBuffer aErrorMsg);
+    private native String serializeJni(byte[] aKey);
 
     /**
      * Loads an account from a pickled base64 string.<br>
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
index 4a1717a87a3c8e1bb94278bf60bc4a84a43bf922..f09ace6571501f9def5f8249313c29f092b02ff9 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
@@ -105,25 +105,27 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi
 * @param aOlmAccountId account instance
 * @param aTheirIdentityKey the identity key of the recipient
 * @param aTheirOneTimeKey the one time key of the recipient
-* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
 **/
-JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer)
+JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer)
 {
-    jint retCode = ERROR_CODE_KO;
+    const char* errorMessage = NULL;
     OlmSession* sessionPtr = NULL;
     OlmAccount* accountPtr = NULL;
 
     if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
     {
         LOGE("## initOutboundSessionJni(): failure - invalid Session ptr=NULL");
+        errorMessage = "invalid Session ptr=NULL";
     }
     else if (!(accountPtr = (OlmAccount*)aOlmAccountId))
     {
         LOGE("## initOutboundSessionJni(): failure - invalid Account ptr=NULL");
+        errorMessage = "invalid Account ptr=NULL";
     }
     else if (!aTheirIdentityKeyBuffer || !aTheirOneTimeKeyBuffer)
     {
         LOGE("## initOutboundSessionJni(): failure - invalid keys");
+        errorMessage = "invalid keys";
     }
     else
     {
@@ -135,6 +137,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject
         if ( (0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize))
         {
             LOGE("## initOutboundSessionJni(): failure - random buffer init");
+            errorMessage = "random buffer init";
         }
         else
         {
@@ -145,10 +148,12 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject
             if (!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0)))
             {
                 LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM");
+                errorMessage = "identityKey JNI allocation OOM";
             }
             else if (!(theirOneTimeKeyPtr = env->GetByteArrayElements(aTheirOneTimeKeyBuffer, 0)))
             {
                 LOGE("## initOutboundSessionJni(): failure - one time Key JNI allocation OOM");
+                errorMessage = "one time Key JNI allocation OOM";
             }
             else
             {
@@ -165,11 +170,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject
                                                             (void*)randomBuffPtr,
                                                             randomSize);
                 if (sessionResult == olm_error()) {
-                    LOGE("## initOutboundSessionJni(): failure - session creation  Msg=%s",(const char *)olm_session_last_error(sessionPtr));
+                    errorMessage = (const char *)olm_session_last_error(sessionPtr);
+                    LOGE("## initOutboundSessionJni(): failure - session creation  Msg=%s", errorMessage);
                 }
                 else
                 {
-                    retCode = ERROR_CODE_OK;
                     LOGD("## initOutboundSessionJni(): success - result=%lu", static_cast<long unsigned int>(sessionResult));
                 }
             }
@@ -191,7 +196,10 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject
         }
     }
 
-    return retCode;
+    if (errorMessage)
+    {
+        env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
+    }
 }
 
 
@@ -203,40 +211,28 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject
  * incoming PRE_KEY message.<br>
  * @param aOlmAccountId account instance
  * @param aOneTimeKeyMsg PRE_KEY message
- * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
  */
-JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer, jobject aErrorMsg)
+JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer)
 {
-    jint retCode = ERROR_CODE_KO;
+    const char* errorMessage = NULL;
     OlmSession *sessionPtr = NULL;
     OlmAccount *accountPtr = NULL;
     size_t sessionResult;
-    jclass errorMsgJClass = 0;
-    jmethodID errorMsgMethodId = 0;
 
     if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
     {
         LOGE("## initInboundSessionJni(): failure - invalid Session ptr=NULL");
+        errorMessage = "invalid Session ptr=NULL";
     }
     else if (!(accountPtr = (OlmAccount*)aOlmAccountId))
     {
         LOGE("## initInboundSessionJni(): failure - invalid Account ptr=NULL");
+        errorMessage = "invalid Account ptr=NULL";
     }
     else if (!aOneTimeKeyMsgBuffer)
     {
         LOGE("## initInboundSessionJni(): failure - invalid message");
-    }
-    else if (!aErrorMsg)
-    {
-        LOGE(" ## initInboundSessionJni(): failure - invalid error output");
-    }
-    else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg)))
-    {
-        LOGE(" ## initInboundSessionJni(): failure - unable to get error class");
-    }
-    else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;")))
-    {
-        LOGE(" ## initInboundSessionJni(): failure - unable to get error method ID");
+        errorMessage = "invalid message";
     }
     else
     {
@@ -245,6 +241,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject
         if (!messagePtr)
         {
             LOGE("## initInboundSessionJni(): failure - message JNI allocation OOM");
+            errorMessage = "message JNI allocation OOM";
         }
         else
         {
@@ -255,19 +252,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject
 
             if (sessionResult == olm_error())
             {
-                const char *errorMsgPtr = olm_session_last_error(sessionPtr);
-                LOGE("## initInboundSessionJni(): failure - init inbound session creation  Msg=%s", errorMsgPtr);
-
-                jstring errorJstring = env->NewStringUTF(errorMsgPtr);
-
-                if (errorJstring)
-                {
-                    env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring);
-                }
+                errorMessage = olm_session_last_error(sessionPtr);
+                LOGE("## initInboundSessionJni(): failure - init inbound session creation  Msg=%s", errorMessage);
             }
             else
             {
-                retCode = ERROR_CODE_OK;
                 LOGD("## initInboundSessionJni(): success - result=%lu", static_cast<long unsigned int>(sessionResult));
             }
 
@@ -275,7 +264,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject
             env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT);
         }
     }
-    return retCode;
+
+    if (errorMessage)
+    {
+        env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
+    }
 }
 
 /**
@@ -284,11 +277,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject
  * @param aOlmAccountId account instance
  * @param aTheirIdentityKey the identity key of the recipient
  * @param aOneTimeKeyMsg encrypted message
- * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
  */
-JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer)
+JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer)
 {
-    jint retCode = ERROR_CODE_KO;
+    const char* errorMessage = NULL;
+
     OlmSession *sessionPtr = NULL;
     OlmAccount *accountPtr = NULL;
     jbyte *messagePtr = NULL;
@@ -298,26 +291,32 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env,
     if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
     {
         LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL");
+        errorMessage = "invalid Session ptr=NULL";
     }
     else if (!(accountPtr = (OlmAccount*)aOlmAccountId))
     {
         LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Account ptr=NULL");
+        errorMessage = "invalid Account ptr=NULL";
     }
     else if (!aTheirIdentityKeyBuffer)
     {
         LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey");
+        errorMessage = "invalid theirIdentityKey";
     }
     else if (!aOneTimeKeyMsgBuffer)
     {
         LOGE("## initInboundSessionJni(): failure - invalid one time key message");
+        errorMessage = "invalid invalid one time key message";
     }
     else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0)))
     {
         LOGE("## initInboundSessionFromIdKeyJni(): failure - message JNI allocation OOM");
+        errorMessage = "message JNI allocation OOM";
     }
     else if(!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0)))
     {
         LOGE("## initInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM");
+        errorMessage = "theirIdentityKey JNI allocation OOM";
     }
     else
     {
@@ -329,11 +328,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env,
         sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength);
         if (sessionResult == olm_error())
         {
-            LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation  Msg=%s",(const char *)olm_session_last_error(sessionPtr));
+            errorMessage = (const char *)olm_session_last_error(sessionPtr);
+            LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation  Msg=%s", errorMessage);
         }
         else
         {
-            retCode = ERROR_CODE_OK;
             LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", static_cast<long unsigned int>(sessionResult));
         }
      }
@@ -349,7 +348,10 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env,
         env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT);
      }
 
-    return retCode;
+     if (errorMessage)
+     {
+         env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
+     }
 }
 
 /**
@@ -475,11 +477,11 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J
  * Encrypt a message using the session.<br>
  * @param aClearMsg clear text message
  * @param [out] aEncryptedMsg ciphered message
- * @return ERROR_CODE_OK if encrypt operation succeed, ERROR_CODE_KO otherwise
  */
-JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg)
+JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg)
 {
-    jint retCode = ERROR_CODE_KO;
+    const char* errorMessage = NULL;
+
     OlmSession *sessionPtr = NULL;
     jbyte *clearMsgPtr = NULL;
     jclass encryptedMsgJClass = 0;
@@ -491,10 +493,12 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
     if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
     {
         LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL");
+        errorMessage = "invalid Session ptr=NULL";
     }
     else if (!aClearMsgBuffer)
     {
         LOGE("## encryptMessageJni(): failure - invalid clear message");
+        errorMessage = "invalid clear message";
     }
     else if (!aEncryptedMsg)
     {
@@ -503,18 +507,22 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
     else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, 0)))
     {
         LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM");
+        errorMessage = "clear message JNI allocation OOM";
     }
     else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg)))
     {
         LOGE("## encryptMessageJni(): failure - unable to get crypted message class");
+        errorMessage = "unable to get crypted message class";
     }
     else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;")))
     {
         LOGE("## encryptMessageJni(): failure - unable to get message field");
+        errorMessage = "unable to get message field";
     }
     else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J")))
     {
         LOGE("## encryptMessageJni(): failure - unable to get message type field");
+        errorMessage = "unable to get message type field";
     }
     else
     {
@@ -532,6 +540,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
         if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength))
         {
             LOGE("## encryptMessageJni(): failure - random buffer init");
+            errorMessage = "random buffer init";
         }
         else
         {
@@ -544,6 +553,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
             if (!encryptedMsgPtr)
             {
                 LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM");
+                errorMessage = "encryptedMsgPtr buffer OOM";
             }
             else
             {
@@ -563,7 +573,8 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
                                             encryptedMsgLength);
                 if (result == olm_error())
                 {
-                    LOGE("## encryptMessageJni(): failure - Msg=%s",(const char *)olm_session_last_error(sessionPtr));
+                    errorMessage = (const char *)olm_session_last_error(sessionPtr);
+                    LOGE("## encryptMessageJni(): failure - Msg=%s", errorMessage);
                 }
                 else
                 {
@@ -577,7 +588,6 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
                     jstring encryptedJstring = env->NewStringUTF((const char*)encryptedMsgPtr);
                     env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring);
 
-                    retCode = ERROR_CODE_OK;
                     LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", static_cast<long unsigned int>(result), static_cast<long unsigned int>(messageType), static_cast<long unsigned int>((size_t)env->GetStringUTFLength(encryptedJstring)), (const char*)encryptedMsgPtr);
                 }
 
@@ -594,16 +604,21 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
         env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT);
     }
 
-    return retCode;
+    if (errorMessage)
+    {
+        env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
+    }
 }
 
 /**
  * Decrypt a message using the session.<br>
  * @param aEncryptedMsg message to decrypt
- * @return decrypted message if operation succeed, null otherwise
+ * @return decrypted message if operation succeed
  */
 JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg)
 {
+    const char* errorMessage = NULL;
+
     jbyteArray decryptedMsgRet = 0;
 
     jclass encryptedMsgJClass = 0;
@@ -622,30 +637,37 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec
     if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
     {
         LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL");
+        errorMessage = "invalid Session ptr=NULL";
     }
     else if (!aEncryptedMsg)
     {
         LOGE("## decryptMessageJni(): failure - invalid encrypted message");
+        errorMessage = "invalid encrypted message";
     }
     else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg)))
     {
         LOGE("## decryptMessageJni(): failure - unable to get encrypted message class");
+        errorMessage = "unable to get encrypted message class";
     }
     else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;")))
     {
         LOGE("## decryptMessageJni(): failure - unable to get message field");
+        errorMessage = "unable to get message field";
     }
     else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J")))
     {
         LOGE("## decryptMessageJni(): failure - unable to get message type field");
+        errorMessage = "unable to get message type field";
     }
     else if (!(encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId)))
     {
         LOGE("## decryptMessageJni(): failure - JNI encrypted object ");
+        errorMessage = "JNI encrypted object";
     }
     else if (!(encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0)))
     {
         LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM");
+        errorMessage = "encrypted message JNI allocation OOM";
     }
     else
     {
@@ -668,7 +690,8 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec
 
         if (maxPlainTextLength == olm_error())
         {
-            LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",(const char *)olm_session_last_error(sessionPtr));
+            errorMessage = (const char *)olm_session_last_error(sessionPtr);
+            LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s", errorMessage);
         }
         else
         {
@@ -687,7 +710,8 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec
                                                  maxPlainTextLength);
             if (plaintextLength == olm_error())
             {
-                LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",(const char *)olm_session_last_error(sessionPtr));
+                errorMessage = (const char *)olm_session_last_error(sessionPtr);
+                LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s", errorMessage);
             }
             else
             {
@@ -715,6 +739,11 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec
         free(plainTextMsgPtr);
     }
 
+    if (errorMessage)
+    {
+        env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
+    }
+
     return decryptedMsgRet;
 }
 
@@ -725,6 +754,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec
 */
 JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz)
 {
+    const char* errorMessage = NULL;
      jbyteArray returnValue = 0;
 
      LOGD("## getSessionIdentifierJni(): IN ");
@@ -734,6 +764,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env,
      if (!sessionPtr)
      {
          LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL");
+         errorMessage = "invalid Session ptr=NULL";
      }
      else
      {
@@ -746,6 +777,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env,
          if (!sessionIdPtr)
          {
             LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM");
+            errorMessage = "identifier allocation OOM";
          }
          else
          {
@@ -753,7 +785,8 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env,
 
              if (result == olm_error())
              {
-                 LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",(const char *)olm_session_last_error(sessionPtr));
+                 errorMessage = (const char *)olm_session_last_error(sessionPtr);
+                 LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s", errorMessage);
              }
              else
              {
@@ -770,6 +803,11 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env,
          }
      }
 
+     if (errorMessage)
+     {
+         env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
+     }
+
      return returnValue;
 }
 
@@ -777,15 +815,13 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env,
 /**
 * Serialize and encrypt session instance into a base64 string.<br>
 * @param aKey key used to encrypt the serialized session data
-* @param[out] aErrorMsg error message set if operation failed
 * @return a base64 string if operation succeed, null otherwise
 **/
-JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg)
+JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer)
 {
+    const char* errorMessage = NULL;
+
     jstring pickledDataRetValue = 0;
-    jclass errorMsgJClass = 0;
-    jmethodID errorMsgMethodId = 0;
-    jstring errorJstring = 0;
     jbyte* keyPtr = NULL;
     OlmSession* sessionPtr = NULL;
 
@@ -794,26 +830,17 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz,
     if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
     {
         LOGE(" ## serializeJni(): failure - invalid session ptr");
+        errorMessage = "invalid session ptr";
     }
     else if (!aKeyBuffer)
     {
         LOGE(" ## serializeJni(): failure - invalid key");
-    }
-    else if (!aErrorMsg)
-    {
-        LOGE(" ## serializeJni(): failure - invalid error object");
-    }
-    else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg)))
-    {
-        LOGE(" ## serializeJni(): failure - unable to get error class");
-    }
-    else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;")))
-    {
-        LOGE(" ## serializeJni(): failure - unable to get error method ID");
+        errorMessage = "invalid key";
     }
     else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0)))
     {
         LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM");
+        errorMessage = "ikeyPtr JNI allocation OOM";
     }
     else
     {
@@ -827,6 +854,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz,
         if (!pickledPtr)
         {
             LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM");
+            errorMessage = "pickledPtr buffer OOM";
         }
         else
         {
@@ -837,13 +865,8 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz,
                                               pickledLength);
             if (result == olm_error())
             {
-                const char *errorMsgPtr = olm_session_last_error(sessionPtr);
-                LOGE(" ## serializeJni(): failure - olm_pickle_session() Msg=%s",errorMsgPtr);
-
-                if ((errorJstring = env->NewStringUTF(errorMsgPtr)))
-                {
-                    env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring);
-                }
+                errorMessage = olm_session_last_error(sessionPtr);
+                LOGE(" ## serializeJni(): failure - olm_pickle_session() Msg=%s", errorMessage);
             }
             else
             {
@@ -863,6 +886,11 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz,
         env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT);
     }
 
+    if (errorMessage)
+    {
+        env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
+    }
+
     return pickledDataRetValue;
 }
 
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
index 95b421b950a9d451381d1a8e7644432593673508..004031e5f48366b32745dff8f520111bb1b388a8 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
@@ -33,24 +33,24 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi
 JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz);
 
 // outbound session
-JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aTheirOneTimeKey);
+JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aTheirOneTimeKey);
 
 // inbound sessions: establishment based on PRE KEY message
-JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg, jobject aErrorMsg);
-JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg);
+JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg);
+JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg);
 
 // match inbound sessions: based on PRE KEY message
 JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg);
 JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg);
 
 // encrypt/decrypt
-JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg);
+JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg);
 JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg);
 
 JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz);
 
 // serialization
-JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg);
+JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey);
 JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey);
 
 #ifdef __cplusplus