diff --git a/test-app/runtime/src/main/cpp/runtime/Runtime.cpp b/test-app/runtime/src/main/cpp/runtime/Runtime.cpp
index d27b568..fba5c5a 100644
--- a/test-app/runtime/src/main/cpp/runtime/Runtime.cpp
+++ b/test-app/runtime/src/main/cpp/runtime/Runtime.cpp
@@ -85,6 +85,7 @@ Runtime::Runtime(JNIEnv *jEnv, jobject runtime, int id)
     m_objectManager = new ObjectManager(m_runtime);
     m_loopTimer = new MessageLoopTimer();
     id_to_runtime_cache.Insert(id, this);
+    pendingError = nullptr;
 
     js_method_cache = new JSMethodCache(this);
 
@@ -604,7 +605,7 @@ jobject Runtime::ConvertJsValueToJavaObject(JEnv &jEnv, napi_value value, int cl
 void
 Runtime::PassExceptionToJsNative(JNIEnv *jEnv, jobject obj, jthrowable exception, jstring message,
                                  jstring fullStackTrace, jstring jsStackTrace,
-                                 jboolean isDiscarded) {
+                                 jboolean isDiscarded, jboolean isPendingError) {
     napi_env napiEnv = env;
 
     std::string errMsg = ArgConverter::jstringToString(message);
@@ -642,7 +643,9 @@ Runtime::PassExceptionToJsNative(JNIEnv *jEnv, jobject obj, jthrowable exception
 
     // Pass err to JS
     NativeScriptException::CallJsFuncWithErr(env, errObj, isDiscarded);
-
+    if (isPendingError) {
+        pendingError = napi_util::make_ref(env, errObj);
+    }
 }
 
 void
diff --git a/test-app/runtime/src/main/cpp/runtime/Runtime.h b/test-app/runtime/src/main/cpp/runtime/Runtime.h
index cc6bb77..4c6f702 100644
--- a/test-app/runtime/src/main/cpp/runtime/Runtime.h
+++ b/test-app/runtime/src/main/cpp/runtime/Runtime.h
@@ -112,7 +112,7 @@ namespace tns {
 
         void
         PassExceptionToJsNative(JNIEnv *env, jobject obj, jthrowable exception, jstring message,
-                                jstring fullStackTrace, jstring jsStackTrace, jboolean isDiscarded);
+                                jstring fullStackTrace, jstring jsStackTrace, jboolean isDiscarded, jboolean isPendingError);
 
         void PassUncaughtExceptionFromWorkerToMainHandler(napi_value message, napi_value stackTrace,
                                                           napi_value filename, int lineno);
@@ -123,7 +123,24 @@ namespace tns {
 
         bool is_destroying = false;
 
+        napi_value getPendingError() {
+            if (!pendingError) return nullptr;
+            napi_value error = napi_util::get_ref_value(env, pendingError);
+            napi_delete_reference(env, pendingError);
+            pendingError = nullptr;
+            return error;
+        }
+
+        void clearPendingError() {
+            if (!pendingError) return;
+            napi_delete_reference(env, pendingError);
+            pendingError = nullptr;
+        }
+
     private:
+        napi_ref pendingError;
+
+
         Runtime(JNIEnv *env, jobject runtime, int id);
 
         static napi_value GlobalAccessorCallback(napi_env env, napi_callback_info info);
diff --git a/test-app/runtime/src/main/cpp/runtime/com_tns_Runtime.cpp b/test-app/runtime/src/main/cpp/runtime/com_tns_Runtime.cpp
index 235eb97..c374f10 100644
--- a/test-app/runtime/src/main/cpp/runtime/com_tns_Runtime.cpp
+++ b/test-app/runtime/src/main/cpp/runtime/com_tns_Runtime.cpp
@@ -241,14 +241,14 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_unlock(JNIEnv* env, jobject obj,
     }
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_passExceptionToJsNative(JNIEnv* jEnv, jobject obj, jint runtimeId, jthrowable exception, jstring message, jstring fullStackTrace, jstring jsStackTrace, jboolean isDiscarded) {
+extern "C" JNIEXPORT void Java_com_tns_Runtime_passExceptionToJsNative(JNIEnv* jEnv, jobject obj, jint runtimeId, jthrowable exception, jstring message, jstring fullStackTrace, jstring jsStackTrace, jboolean isDiscarded, jboolean isPendingError) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) return;
 
     NapiScope scope(runtime->GetNapiEnv());
 
     try {
-        runtime->PassExceptionToJsNative(jEnv, obj, exception, message, fullStackTrace, jsStackTrace, isDiscarded);
+        runtime->PassExceptionToJsNative(jEnv, obj, exception, message, fullStackTrace, jsStackTrace, isDiscarded, isPendingError);
     } catch (NativeScriptException& e) {
         e.ReThrowToJava(runtime->GetNapiEnv());
     } catch (std::exception e) {
diff --git a/test-app/runtime/src/main/cpp/runtime/metadata/MetadataNode.cpp b/test-app/runtime/src/main/cpp/runtime/metadata/MetadataNode.cpp
index d727afd..faa7d7d 100644
--- a/test-app/runtime/src/main/cpp/runtime/metadata/MetadataNode.cpp
+++ b/test-app/runtime/src/main/cpp/runtime/metadata/MetadataNode.cpp
@@ -1986,13 +1986,21 @@ napi_value MetadataNode::MethodCallback(napi_env env, napi_callback_info info) {
             }
         }
 
+
         if (argc == 0 && methodName == PROP_KEY_VALUEOF) {
             return jsThis;
         } else {
+            Runtime::GetRuntime(env)->clearPendingError();
             bool isFromInterface = initialCallbackData->node->IsNodeTypeInterface();
-            return CallbackHandlers::CallJavaMethod(env, jsThis, *className, methodName, entry,
+            napi_value result = CallbackHandlers::CallJavaMethod(env, jsThis, *className, methodName, entry,
                                                     isFromInterface, first.isStatic, info,
                                                     argc, argv.data());
+            napi_value error;
+            error = Runtime::GetRuntime(env)->getPendingError();
+            if (error) {
+                throw NativeScriptException(env, error);
+            }
+            return result;
         }
 
     } catch (NativeScriptException &e) {
diff --git a/test-app/runtime/src/main/java/com/tns/Runtime.java b/test-app/runtime/src/main/java/com/tns/Runtime.java
index b286519..c2d1566 100644
--- a/test-app/runtime/src/main/java/com/tns/Runtime.java
+++ b/test-app/runtime/src/main/java/com/tns/Runtime.java
@@ -37,8 +37,6 @@
 import java.util.concurrent.RunnableFuture;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import dalvik.annotation.optimization.FastNative;
-
 public class Runtime {
     private native void initNativeScript(int runtimeId, String filesPath, String nativeLibDir, boolean verboseLoggingEnabled, boolean isDebuggable, String packageName,
                                          Object[] v8Options, String callingDir, int maxLogcatObjectSize, boolean forceLog);
@@ -61,7 +59,7 @@ private native void initNativeScript(int runtimeId, String filesPath, String nat
 
     private native void unlock(int runtimeId);
 
-    private native void passExceptionToJsNative(int runtimeId, Throwable ex, String message, String fullStackTrace, String jsStackTrace, boolean isDiscarded);
+    private native void passExceptionToJsNative(int runtimeId, Throwable ex, String message, String fullStackTrace, String jsStackTrace, boolean isDiscarded, boolean isPendingError);
 
     private static native int getCurrentRuntimeId();
 
@@ -82,21 +80,21 @@ private native void initNativeScript(int runtimeId, String filesPath, String nat
     private static native void ResetDateTimeConfigurationCache(int runtimeId);
 
     void passUncaughtExceptionToJs(Throwable ex, String message, String fullStackTrace, String jsStackTrace) {
-        passExceptionToJsNative(getRuntimeId(), ex, message, fullStackTrace, jsStackTrace, false);
+        passExceptionToJsNative(getRuntimeId(), ex, message, fullStackTrace, jsStackTrace, false, false);
     }
 
-    void passDiscardedExceptionToJs(Throwable ex, String prefix) {
+    void passExceptionToJS(Throwable ex, boolean isPendingError, boolean isDiscarded) {
         //String message = prefix + ex.getMessage();
         // we'd better not prefix the error with something like - Error on "main" thread for reportSupressedException
         // as it doesn't seem very useful for the users
-        passExceptionToJsNative(getRuntimeId(), ex, ex.getMessage(), Runtime.getStackTraceErrorMessage(ex), Runtime.getJSStackTrace(ex), true);
+        passExceptionToJsNative(getRuntimeId(), ex, ex.getMessage(), Runtime.getStackTraceErrorMessage(ex), Runtime.getJSStackTrace(ex), isDiscarded, isPendingError);
     }
 
     public static void passSuppressedExceptionToJs(Throwable ex, String methodName) {
         com.tns.Runtime runtime = com.tns.Runtime.getCurrentRuntime();
         if (runtime != null) {
             String errorMessage = "Error on \"" + Thread.currentThread().getName() + "\" thread for " + methodName + "\n";
-            runtime.passDiscardedExceptionToJs(ex, "");
+            runtime.passExceptionToJS(ex, false , false);
         }
     }
 
@@ -668,7 +666,6 @@ private void init(Logger logger, String appName, String nativeLibDir, File rootD
 
     @RuntimeCallable
     public void enableVerboseLogging() {
-
         logger.setEnabled(true);
         ProxyGenerator.IsLogEnabled = true;
     }
@@ -676,70 +673,84 @@ public void enableVerboseLogging() {
 
     @RuntimeCallable
     public void disableVerboseLogging() {
-//        logger.setEnabled(false);
-//        ProxyGenerator.IsLogEnabled = false;
+        logger.setEnabled(false);
+        ProxyGenerator.IsLogEnabled = false;
     }
 
-    public void run() throws NativeScriptException {
+    public void run() {
         ManualInstrumentation.Frame frame = ManualInstrumentation.start("Runtime.run");
         try {
             String mainModule = Module.bootstrapApp();
             runModule(new File(mainModule));
+        } catch (NativeScriptException e){
+            passExceptionToJS(e, false, false);
         } finally {
             frame.close();
         }
     }
 
-    public void runModule(File jsFile) throws NativeScriptException {
-        String filePath = jsFile.getPath();
-        runModule(getRuntimeId(), filePath);
+    public void runModule(File jsFile) {
+        try {
+            String filePath = jsFile.getPath();
+            runModule(getRuntimeId(), filePath);
+        } catch (NativeScriptException ex) {
+            passExceptionToJS(ex, false, false);
+        }
     }
 
-    public Object runScript(File jsFile) throws NativeScriptException {
-        return this.runScript(jsFile, true);
+    public Object runScript(File jsFile) {
+        try {
+            return this.runScript(jsFile, true);
+        } catch (NativeScriptException ex) {
+            passExceptionToJS(ex, false, false);
+            return null;
+        }
     }
 
-    public Object runScript(File jsFile, final boolean waitForResultOnMainThread) throws NativeScriptException {
+    public Object runScript(File jsFile, final boolean waitForResultOnMainThread) {
         Object result = null;
+        try {
+            if (jsFile.exists() && jsFile.isFile()) {
+                final String filePath = jsFile.getAbsolutePath();
 
-        if (jsFile.exists() && jsFile.isFile()) {
-            final String filePath = jsFile.getAbsolutePath();
-
-            boolean isWorkThread = threadScheduler.getThread().equals(Thread.currentThread());
+                boolean isWorkThread = threadScheduler.getThread().equals(Thread.currentThread());
 
-            if (isWorkThread) {
-                result = runScript(getRuntimeId(), filePath);
-            } else {
-                final Object[] arr = new Object[2];
-
-                Runnable r = new Runnable() {
-                    @Override
-                    public void run() {
-                        synchronized (this) {
-                            try {
-                                arr[0] = runScript(getRuntimeId(), filePath);
-                            } finally {
-                                this.notify();
-                                arr[1] = Boolean.TRUE;
+                if (isWorkThread) {
+                    result = runScript(getRuntimeId(), filePath);
+                } else {
+                    final Object[] arr = new Object[2];
+
+                    Runnable r = new Runnable() {
+                        @Override
+                        public void run() {
+                            synchronized (this) {
+                                try {
+                                    arr[0] = runScript(getRuntimeId(), filePath);
+                                } finally {
+                                    this.notify();
+                                    arr[1] = Boolean.TRUE;
+                                }
                             }
                         }
-                    }
-                };
+                    };
 
-                boolean success = threadScheduler.post(r);
+                    boolean success = threadScheduler.post(r);
 
-                if (success) {
-                    synchronized (r) {
-                        try {
-                            if (arr[1] == null && waitForResultOnMainThread) {
-                                r.wait();
+                    if (success) {
+                        synchronized (r) {
+                            try {
+                                if (arr[1] == null && waitForResultOnMainThread) {
+                                    r.wait();
+                                }
+                            } catch (InterruptedException e) {
+                                result = e;
                             }
-                        } catch (InterruptedException e) {
-                            result = e;
                         }
                     }
                 }
             }
+        } catch (NativeScriptException ex) {
+            passExceptionToJS(ex, false, false);
         }
 
         return result;
@@ -1116,9 +1127,6 @@ private Object getJavaObjectByID(int javaObjectID) throws Exception {
             }
         }
 
-        // Log.d(DEFAULT_LOG_TAG,
-        // "Platform.getJavaObjectByID found strong object with id:" +
-        // javaObjectID);
         return instance;
     }
 
@@ -1344,13 +1352,13 @@ private Object dispatchCallJSMethodNative(final int javaObjectID, Class<?> claz,
             try {
                 ret = callJSMethodNative(getRuntimeId(), javaObjectID, claz, methodName, returnType, isConstructor, packagedArgs);
             } catch (NativeScriptException e) {
-                if (discardUncaughtJsExceptions) {
+//                if (discardUncaughtJsExceptions) {
                     String errorMessage = "Error on \"" + Thread.currentThread().getName() + "\" thread for callJSMethodNative\n";
-                    android.util.Log.w("Warning", "NativeScript discarding uncaught JS exception!");
-                    passDiscardedExceptionToJs(e, errorMessage);
-                } else {
-                    throw e;
-                }
+//                    android.util.Log.w("Warning", "NativeScript discarding uncaught JS exception!");
+                    passExceptionToJS(e, true, true);
+//                } else {
+//                    throw e;
+//                }
             }
         } else {
             final Object[] arr = new Object[2];
@@ -1365,13 +1373,13 @@ public void run() {
                             final Object[] packagedArgs = packageArgs(tmpArgs);
                             arr[0] = callJSMethodNative(getRuntimeId(), javaObjectID, claz, methodName, returnType, isCtor, packagedArgs);
                         } catch (NativeScriptException e) {
-                            if (discardUncaughtJsExceptions) {
+//                            if (discardUncaughtJsExceptions) {
                                 String errorMessage = "Error on \"" + Thread.currentThread().getName() + "\" thread for callJSMethodNative\n";
-                                passDiscardedExceptionToJs(e, errorMessage);
-                                android.util.Log.w("Warning", "NativeScript discarding uncaught JS exception!");
-                            } else {
-                                throw e;
-                            }
+                                passExceptionToJS(e, true, false);
+//                                android.util.Log.w("Warning", "NativeScript discarding uncaught JS exception!");
+//                            } else {
+//                                throw e;
+//                            }
                         } finally {
                             this.notify();
                             arr[1] = Boolean.TRUE;