diff --git a/app/services/exercise_service/push_external.rb b/app/services/exercise_service/push_external.rb
index 69c5234a2..a00009a70 100644
--- a/app/services/exercise_service/push_external.rb
+++ b/app/services/exercise_service/push_external.rb
@@ -17,17 +17,29 @@ def execute
           request.headers['Authorization'] = "Bearer #{@codeharbor_link.api_key}"
           request.body = body
         end
+        return nil if response.success?
+        return I18n.t('exercises.export_codeharbor.not_authorized') if response.status == 401
 
-        response.success? ? nil : response.body
+        handle_error(message: response.body)
+      rescue Faraday::ServerError => e
+        handle_error(error: e, message: I18n.t('exercises.export_codeharbor.server_error'))
       rescue StandardError => e
-        e.message
+        handle_error(error: e)
       end
     end
 
     private
 
+    def handle_error(message: nil, error: nil)
+      Sentry.capture_exception(error) if error.present?
+      ERB::Util.html_escape(message || error.to_s)
+    end
+
     def connection
       Faraday.new(url: @codeharbor_link.push_url) do |faraday|
+        faraday.options[:open_timeout] = 5
+        faraday.options[:timeout] = 5
+
         faraday.adapter Faraday.default_adapter
       end
     end
diff --git a/config/locales/de/exercise.yml b/config/locales/de/exercise.yml
index 97b144bfb..7e9070ce4 100644
--- a/config/locales/de/exercise.yml
+++ b/config/locales/de/exercise.yml
@@ -102,6 +102,8 @@ de:
       error: Es ist ein Fehler bei der Kommunikation mit CodeHarbor aufgetreten.
       export_failed: 'Export ist fehlgeschlagen.<br>ID: %{id}<br>Title: %{title}<br><br>Error: %{error}'
       label: Zu CodeHarbor exportieren
+      not_authorized: Die Autorisierung mit CodeHarbor konnte nicht hergestellt werden. Ist der API-Schlüssel korrekt?
+      server_error: Verbindung zu CodeHarbor fehlgeschlagen. Gegenseite nicht erreichbar.
       successfully_exported: 'Aufgabe wurde erfolgreich exportiert.<br>ID: %{id}<br>Title: %{title}'
     external_users:
       statistics:
diff --git a/config/locales/en/exercise.yml b/config/locales/en/exercise.yml
index 3f9e04b15..704acc4c9 100644
--- a/config/locales/en/exercise.yml
+++ b/config/locales/en/exercise.yml
@@ -102,6 +102,8 @@ en:
       error: An error occurred while contacting CodeHarbor
       export_failed: 'Export has failed.<br>ID: %{id}<br>Title: %{title}<br><br>Error: %{error}'
       label: Export to CodeHarbor
+      not_authorized: Authorization with could not be established with CodeHarbor. Is the API Key correct?
+      server_error: Connection to CodeHarbor failed. Remote host unreachable.
       successfully_exported: 'Exercise has been successfully exported.<br>ID: %{id}<br>Title: %{title}'
     external_users:
       statistics:
diff --git a/spec/services/exercise_service/push_external_spec.rb b/spec/services/exercise_service/push_external_spec.rb
index 347d3d86e..8bc74b456 100644
--- a/spec/services/exercise_service/push_external_spec.rb
+++ b/spec/services/exercise_service/push_external_spec.rb
@@ -49,9 +49,40 @@
 
       context 'when response status is 500' do
         let(:status) { 500 }
-        let(:response) { 'an error occured' }
+        let(:response) { 'an error occurred' }
 
-        it { is_expected.to be response }
+        it { is_expected.to eql response }
+
+        context 'when response contains problematic characters' do
+          let(:response) { 'an <error> occurred' }
+
+          it { is_expected.to eql 'an &lt;error&gt; occurred' }
+        end
+
+        context 'when faraday throws an error' do
+          let(:connection) { instance_double(Faraday::Connection) }
+          let(:error) { Faraday::ServerError }
+
+          before do
+            allow(Faraday).to receive(:new).and_return(connection)
+            allow(connection).to receive(:post).and_raise(error)
+          end
+
+          it { is_expected.to eql I18n.t('exercises.export_codeharbor.server_error') }
+
+          context 'when another error occurs' do
+            let(:error) { 'another error' }
+
+            it { is_expected.to eql 'another error' }
+          end
+        end
+      end
+
+      context 'when response status is 401' do
+        let(:status) { 401 }
+        let(:response) { I18n.t('exercises.export_codeharbor.not_authorized') }
+
+        it { is_expected.to eql response }
       end
     end