Index: /trunk/src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 29964)
+++ /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 29965)
@@ -212,5 +212,4 @@
                   Progress *aProgress)
         : VMProgressTask(aConsole, aProgress, false /* aUsesVMPtr */),
-          mSetVMErrorCallback(NULL),
           mConfigConstructor(NULL),
           mStartPaused(false),
@@ -218,5 +217,4 @@
     {}
 
-    PFNVMATERROR mSetVMErrorCallback;
     PFNCFGMCONSTRUCTOR mConfigConstructor;
     Utf8Str mSavedStateFile;
@@ -5271,5 +5269,4 @@
     ComAssertComRCRetRC(task->rc());
 
-    task->mSetVMErrorCallback = setVMErrorCallback;
     task->mConfigConstructor = configConstructor;
     task->mSharedFolders = sharedFolders;
@@ -6871,38 +6868,28 @@
 
 /**
- * VM error callback function. Called by the various VM components.
- *
- * @param   pVM         VM handle. Can be NULL if an error occurred before
- *                      successfully creating a VM.
- * @param   pvUser      Pointer to the VMProgressTask structure.
- * @param   rc          VBox status code.
- * @param   pszFormat   Printf-like error message.
- * @param   args        Various number of arguments for the error message.
- *
- * @thread EMT, VMPowerUp...
- *
- * @note The VMProgressTask structure modified by this callback is not thread
- *       safe.
+ * @copydoc FNVMATERROR
+ *
+ * @remarks Might be some tiny serialization concerns with access to the string
+ *          object here...
  */
-/* static */ DECLCALLBACK(void)
-Console::setVMErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
-                            const char *pszFormat, va_list args)
-{
-    VMProgressTask *task = static_cast<VMProgressTask *>(pvUser);
-    AssertReturnVoid(task);
-
-    /* we ignore RT_SRC_POS_DECL arguments to avoid confusion of end-users */
+/*static*/ DECLCALLBACK(void)
+Console::genericVMSetErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
+                                   const char *pszErrorFmt, va_list va)
+{
+    Utf8Str *pErrorText = (Utf8Str *)pvUser;
+    AssertPtr(pErrorText);
+
+    /* We ignore RT_SRC_POS_DECL arguments to avoid confusion of end-users. */
     va_list va2;
-    va_copy(va2, args); /* Have to make a copy here or GCC will break. */
-
-    /* append to the existing error message if any */
-    if (task->mErrorMsg.length())
-        task->mErrorMsg = Utf8StrFmt("%s.\n%N (%Rrc)", task->mErrorMsg.raw(),
-                                     pszFormat, &va2, rc, rc);
+    va_copy(va2, va);
+
+    /* Append to any the existing error message. */
+    if (pErrorText->length())
+        *pErrorText = Utf8StrFmt("%s.\n%N (%Rrc)", pErrorText->c_str(),
+                                 pszErrorFmt, &va2, rc, rc);
     else
-        task->mErrorMsg = Utf8StrFmt("%N (%Rrc)",
-                                     pszFormat, &va2, rc, rc);
-
-    va_end (va2);
+        *pErrorText = Utf8StrFmt("%N (%Rrc)", pszErrorFmt, &va2, rc, rc);
+
+    va_end(va2);
 }
 
@@ -7302,5 +7289,5 @@
         alock.leave();
 
-        vrc = VMR3Create(cCpus, task->mSetVMErrorCallback, task.get(),
+        vrc = VMR3Create(cCpus, Console::genericVMSetErrorCallback, &task->mErrorMsg,
                          task->mConfigConstructor, static_cast<Console *>(console),
                          &pVM);
@@ -7451,5 +7438,5 @@
                  */
                 alock.leave();
-                VMR3AtErrorDeregister(pVM, task->mSetVMErrorCallback, task.get());
+                VMR3AtErrorDeregister(pVM, Console::genericVMSetErrorCallback, &task->mErrorMsg);
                 /** @todo register another VMSetError callback? */
                 alock.enter();
Index: /trunk/src/VBox/Main/ConsoleImplTeleporter.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImplTeleporter.cpp	(revision 29964)
+++ /trunk/src/VBox/Main/ConsoleImplTeleporter.cpp	(revision 29965)
@@ -121,4 +121,5 @@
     bool                        mfLockedMedia;
     int                         mRc;
+    Utf8Str                     mErrorText;
 
     TeleporterStateTrg(Console *pConsole, PVM pVM, Progress *pProgress,
@@ -132,4 +133,5 @@
         , mfLockedMedia(false)
         , mRc(VINF_SUCCESS)
+        , mErrorText()
     {
     }
@@ -219,29 +221,53 @@
 HRESULT
 Console::teleporterSrcReadACK(TeleporterStateSrc *pState, const char *pszWhich,
-                             const char *pszNAckMsg /*= NULL*/)
-{
-    char szMsg[128];
+                              const char *pszNAckMsg /*= NULL*/)
+{
+    char szMsg[256];
     int vrc = teleporterTcpReadLine(pState, szMsg, sizeof(szMsg));
     if (RT_FAILURE(vrc))
         return setError(E_FAIL, tr("Failed reading ACK(%s): %Rrc"), pszWhich, vrc);
-    if (strcmp(szMsg, "ACK"))
-    {
-        if (!strncmp(szMsg, "NACK=", sizeof("NACK=") - 1))
-        {
-            int32_t vrc2;
-            vrc = RTStrToInt32Full(&szMsg[sizeof("NACK=") - 1], 10, &vrc2);
-            if (vrc == VINF_SUCCESS)
-            {
-                if (pszNAckMsg)
-                {
-                    LogRel(("Teleporter: %s: NACK=%Rrc (%d)\n", pszWhich, vrc2, vrc2));
-                    return setError(E_FAIL, pszNAckMsg);
-                }
-                return setError(E_FAIL, "NACK(%s) - %Rrc (%d)", pszWhich, vrc2, vrc2);
-            }
-        }
-        return setError(E_FAIL, tr("%s: Expected ACK or NACK, got '%s'"), pszWhich, szMsg);
-    }
-    return S_OK;
+
+    if (!strcmp(szMsg, "ACK"))
+        return S_OK;
+
+    if (!strncmp(szMsg, "NACK=", sizeof("NACK=") - 1))
+    {
+        char *pszMsgText = strchr(szMsg, ';');
+        if (pszMsgText)
+            *pszMsgText++ = '\0';
+
+        int32_t vrc2;
+        vrc = RTStrToInt32Full(&szMsg[sizeof("NACK=") - 1], 10, &vrc2);
+        if (vrc == VINF_SUCCESS)
+        {
+            /*
+             * Well formed NACK, transform it into an error.
+             */
+            if (pszNAckMsg)
+            {
+                LogRel(("Teleporter: %s: NACK=%Rrc (%d)\n", pszWhich, vrc2, vrc2));
+                return setError(E_FAIL, pszNAckMsg);
+            }
+
+            if (pszMsgText)
+            {
+                pszMsgText = RTStrStrip(pszMsgText);
+                for (size_t off = 0; pszMsgText[off]; off++)
+                    if (pszMsgText[off] == '\r')
+                        pszMsgText[off] = '\n';
+
+                LogRel(("Teleporter: %s: NACK=%Rrc (%d) - '%s'\n", pszWhich, vrc2, vrc2, pszMsgText));
+                if (strlen(pszMsgText) > 4)
+                    return setError(E_FAIL, "%s", pszMsgText);
+                return setError(E_FAIL, "NACK(%s) - %Rrc (%d) '%s'", pszWhich, vrc2, vrc2, pszMsgText);
+            }
+
+            return setError(E_FAIL, "NACK(%s) - %Rrc (%d)", pszWhich, vrc2, vrc2);
+        }
+
+        if (pszMsgText)
+            pszMsgText[-1] = ';';
+    }
+    return setError(E_FAIL, tr("%s: Expected ACK or NACK, got '%s'"), pszWhich, szMsg);
 }
 
@@ -672,5 +698,14 @@
     RTSocketRelease(pState->mhSocket);
     if (RT_FAILURE(vrc))
+    {
+        if (   vrc == VERR_SSM_CANCELLED
+            && RT_SUCCESS(RTTcpSelectOne(pState->mhSocket, 1)))
+        {
+            hrc = teleporterSrcReadACK(pState, "load-complete");
+            if (FAILED(hrc))
+                return hrc;
+        }
         return setError(E_FAIL, tr("VMR3Teleport -> %Rrc"), vrc);
+    }
 
     hrc = teleporterSrcReadACK(pState, "load-complete");
@@ -1179,5 +1214,5 @@
 
 
-static int teleporterTcpWriteNACK(TeleporterStateTrg *pState, int32_t rc2)
+static int teleporterTcpWriteNACK(TeleporterStateTrg *pState, int32_t rc2, const char *pszMsgText = NULL)
 {
     /*
@@ -1187,6 +1222,15 @@
     teleporterTrgUnlockMedia(pState);
 
-    char    szMsg[64];
-    size_t  cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d\n", rc2);
+    char    szMsg[256];
+    size_t  cch;
+    if (pszMsgText && *pszMsgText)
+    {
+        cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d;%s\n", rc2, pszMsgText);
+        for (size_t off = 6; off + 1 < cch; off++)
+            if (szMsg[off] == '\n')
+                szMsg[off] = '\r';
+    }
+    else
+        cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d\n", rc2);
     int rc = RTTcpWrite(pState->mhSocket, szMsg, cch);
     if (RT_FAILURE(rc))
@@ -1288,14 +1332,19 @@
                 break;
 
+            int vrc2 = VMR3AtErrorRegister(pState->mpVM, Console::genericVMSetErrorCallback, &pState->mErrorText); AssertRC(vrc2);
             RTSocketRetain(pState->mhSocket); /* For concurrent access by I/O thread and EMT. */
             pState->moffStream = 0;
+
             void *pvUser2 = static_cast<void *>(static_cast<TeleporterState *>(pState));
             vrc = VMR3LoadFromStream(pState->mpVM, &g_teleporterTcpOps, pvUser2,
                                      teleporterProgressCallback, pvUser2);
+
             RTSocketRelease(pState->mhSocket);
+            vrc2 = VMR3AtErrorDeregister(pState->mpVM, Console::genericVMSetErrorCallback, &pState->mErrorText); AssertRC(vrc2);
+
             if (RT_FAILURE(vrc))
             {
                 LogRel(("Teleporter: VMR3LoadFromStream -> %Rrc\n", vrc));
-                teleporterTcpWriteNACK(pState, vrc);
+                teleporterTcpWriteNACK(pState, vrc, pState->mErrorText.c_str());
                 break;
             }
Index: /trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 29964)
+++ /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 29965)
@@ -519,6 +519,6 @@
     static DECLCALLBACK(int)    stateProgressCallback(PVM pVM, unsigned uPercent, void *pvUser);
 
-    static DECLCALLBACK(void)   setVMErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
-                                                   const char *pszFormat, va_list args);
+    static DECLCALLBACK(void)   genericVMSetErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
+                                                          const char *pszErrorFmt, va_list va);
 
     static DECLCALLBACK(void) setVMRuntimeErrorCallbackF(PVM pVM, void *pvUser, uint32_t fFatal,
