diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp
index 047e03bf2..cfae9edd1 100644
--- a/src/libslic3r/Utils.hpp
+++ b/src/libslic3r/Utils.hpp
@@ -11,6 +11,7 @@
 namespace Slic3r {
 
 extern void set_logging_level(unsigned int level);
+extern unsigned get_logging_level();
 extern void trace(unsigned int level, const char *message);
 // Format memory allocated, separate thousands by comma.
 extern std::string format_memsize_MB(size_t n);
diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp
index 18e27f34b..f48abfd89 100644
--- a/src/libslic3r/utils.cpp
+++ b/src/libslic3r/utils.cpp
@@ -59,6 +59,18 @@ void set_logging_level(unsigned int level)
     );
 }
 
+unsigned get_logging_level()
+{
+    switch (logSeverity) {
+    case boost::log::trivial::fatal : return 0;
+    case boost::log::trivial::error : return 1;
+    case boost::log::trivial::warning : return 2;
+    case boost::log::trivial::info : return 3;
+    case boost::log::trivial::debug : return 4;
+    default: return 1;
+    }
+}
+
 // Force set_logging_level(<=error) after loading of the DLL.
 // Switch boost::filesystem to utf8.
 static struct RunOnInit {
diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp
index ae7b40484..d6b8b438e 100644
--- a/src/slic3r/GUI/MsgDialog.cpp
+++ b/src/slic3r/GUI/MsgDialog.cpp
@@ -6,6 +6,7 @@
 #include <wx/button.h>
 #include <wx/statbmp.h>
 #include <wx/scrolwin.h>
+#include <wx/clipbrd.h>
 
 #include "libslic3r/libslic3r.h"
 #include "libslic3r/Utils.hpp"
@@ -61,8 +62,11 @@ MsgDialog::~MsgDialog() {}
 
 // ErrorDialog
 
-ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg) :
-	MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")), wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png")), wxBITMAP_TYPE_PNG))
+ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
+	: MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")),
+		wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png")), wxBITMAP_TYPE_PNG),
+		wxID_NONE)
+	, msg(msg)
 {
 	auto *panel = new wxScrolledWindow(this);
 	auto *p_sizer = new wxBoxSizer(wxVERTICAL);
@@ -77,6 +81,20 @@ ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg) :
 
 	content_sizer->Add(panel, 1, wxEXPAND);
 
+	auto *btn_copy = new wxButton(this, wxID_ANY, _(L("Copy to clipboard")));
+	btn_copy->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) {
+		if (wxTheClipboard->Open()) {
+			wxTheClipboard->SetData(new wxTextDataObject(this->msg));   // Note: the clipboard takes ownership of the pointer
+			wxTheClipboard->Close();
+		}
+	});
+
+	auto *btn_ok = new wxButton(this, wxID_OK);
+	btn_ok->SetFocus();
+
+	btn_sizer->Add(btn_copy, 0, wxRIGHT, HORIZ_SPACING);
+	btn_sizer->Add(btn_ok);
+
 	SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT));
 	Fit();
 }
diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp
index ca349eb5c..6064d2a9f 100644
--- a/src/slic3r/GUI/MsgDialog.hpp
+++ b/src/slic3r/GUI/MsgDialog.hpp
@@ -50,14 +50,18 @@ protected:
 
 
 // Generic error dialog, used for displaying exceptions
-struct ErrorDialog : MsgDialog
+class ErrorDialog : public MsgDialog
 {
+public:
 	ErrorDialog(wxWindow *parent, const wxString &msg);
 	ErrorDialog(ErrorDialog &&) = delete;
 	ErrorDialog(const ErrorDialog &) = delete;
 	ErrorDialog &operator=(ErrorDialog &&) = delete;
 	ErrorDialog &operator=(const ErrorDialog &) = delete;
 	virtual ~ErrorDialog();
+
+private:
+	wxString msg;
 };
 
 
diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp
index 67c24f3f4..6e6c9ed44 100644
--- a/src/slic3r/Utils/Http.cpp
+++ b/src/slic3r/Utils/Http.cpp
@@ -11,6 +11,7 @@
 #include <curl/curl.h>
 
 #include "libslic3r/libslic3r.h"
+#include "libslic3r/Utils.hpp"
 
 namespace fs = boost::filesystem;
 
@@ -44,6 +45,7 @@ struct Http::priv
 	// Using a deque here because unlike vector it doesn't ivalidate pointers on insertion
 	std::deque<fs::ifstream> form_files;
 	std::string postfields;
+	std::string error_buffer;    // Used for CURLOPT_ERRORBUFFER
 	size_t limit;
 	bool cancel;
 
@@ -69,13 +71,14 @@ struct Http::priv
 	void http_perform();
 };
 
-Http::priv::priv(const std::string &url) :
-	curl(::curl_easy_init()),
-	form(nullptr),
-	form_end(nullptr),
-	headerlist(nullptr),
-	limit(0),
-	cancel(false)
+Http::priv::priv(const std::string &url)
+	: curl(::curl_easy_init())
+	, form(nullptr)
+	, form_end(nullptr)
+	, headerlist(nullptr)
+	, error_buffer(CURL_ERROR_SIZE + 1, '\0')
+	, limit(0)
+	, cancel(false)
 {
 	if (curl == nullptr) {
 		throw std::runtime_error(std::string("Could not construct Curl object"));
@@ -83,6 +86,7 @@ Http::priv::priv(const std::string &url) :
 
 	::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());   // curl makes a copy internally
 	::curl_easy_setopt(curl, CURLOPT_USERAGENT, SLIC3R_FORK_NAME "/" SLIC3R_VERSION);
+	::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer.front());
 }
 
 Http::priv::~priv()
@@ -199,9 +203,10 @@ void Http::priv::set_post_body(const fs::path &path)
 
 std::string Http::priv::curl_error(CURLcode curlcode)
 {
-	return (boost::format("%1% (%2%)")
+	return (boost::format("%1% (%2%): %3%")
 		% ::curl_easy_strerror(curlcode)
 		% curlcode
+		% error_buffer
 	).str();
 }
 
@@ -227,9 +232,7 @@ void Http::priv::http_perform()
 	::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, static_cast<void*>(this));
 #endif
 
-#ifndef NDEBUG
-	::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
-#endif
+	::curl_easy_setopt(curl, CURLOPT_VERBOSE, get_logging_level() >= 4);
 
 	if (headerlist != nullptr) {
 		::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
diff --git a/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp
index 863da5d43..cdd0c107e 100644
--- a/src/slic3r/Utils/PrintHost.cpp
+++ b/src/slic3r/Utils/PrintHost.cpp
@@ -3,6 +3,7 @@
 #include <vector>
 #include <thread>
 #include <boost/optional.hpp>
+#include <boost/log/trivial.hpp>
 #include <boost/filesystem.hpp>
 
 #include <wx/app.h>
@@ -144,6 +145,10 @@ void PrintHostJobQueue::priv::perform_job(PrintHostJob the_job)
 {
     if (bg_exit || the_job.empty()) { return; }
 
+    BOOST_LOG_TRIVIAL(debug) << boost::format("PrintHostJobQueue/bg_thread: Got job: `%1%` -> `%1%`")
+        % the_job.upload_data.upload_path
+        % the_job.printhost->get_host();
+
     const fs::path gcode_path = the_job.upload_data.source_path;
 
     the_job.printhost->upload(std::move(the_job.upload_data),
@@ -154,7 +159,11 @@ void PrintHostJobQueue::priv::perform_job(PrintHostJob the_job)
     auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_PROGRESS, queue_dialog->GetId(), job_id, 100);
     wxQueueEvent(queue_dialog, evt);
 
-    fs::remove(gcode_path);   // XXX: error handling
+    boost::system::error_code ec;
+    fs::remove(gcode_path, ec);
+    if (ec) {
+        BOOST_LOG_TRIVIAL(error) << boost::format("PrintHostJobQueue: Error removing file `%1%`: %2%") % gcode_path % ec;
+    }
 }
 
 void PrintHostJobQueue::enqueue(PrintHostJob job)