diff --git a/components/renderers/cpp/include/ftl/render/CUDARender.hpp b/components/renderers/cpp/include/ftl/render/CUDARender.hpp
index d5b3ce6755b64630268866f18af88c46d48875d9..a4e65bce6ba1aa40dbce3c4a8ba24747f258300a 100644
--- a/components/renderers/cpp/include/ftl/render/CUDARender.hpp
+++ b/components/renderers/cpp/include/ftl/render/CUDARender.hpp
@@ -33,6 +33,8 @@ class CUDARender : public ftl::render::FSRenderer {
 
 	void blend(ftl::codecs::Channel) override;
 
+	void cancel() override;
+
 	/**
 	 * Returns all inter-frameset collisions in camera coordinates.
 	 */
diff --git a/components/renderers/cpp/include/ftl/render/renderer.hpp b/components/renderers/cpp/include/ftl/render/renderer.hpp
index 07f92083e33bac9ed3e4002c3be912ef9c98da91..598e2a6eeb2b9fcd87cd4aceb146cabf3b605e16 100644
--- a/components/renderers/cpp/include/ftl/render/renderer.hpp
+++ b/components/renderers/cpp/include/ftl/render/renderer.hpp
@@ -47,6 +47,8 @@ class Renderer : public ftl::Configurable {
 
 	virtual void blend(ftl::codecs::Channel)=0;
 
+	virtual void cancel()=0;
+
 	protected:
 	Stage stage_;
 };
diff --git a/components/renderers/cpp/src/CUDARender.cpp b/components/renderers/cpp/src/CUDARender.cpp
index b3d07ac298125d39f206469b5c7472d3bbb54ce2..b2973f0a7a8e89ffb114a0f0d7c7518273b65a3f 100644
--- a/components/renderers/cpp/src/CUDARender.cpp
+++ b/components/renderers/cpp/src/CUDARender.cpp
@@ -498,6 +498,13 @@ void CUDARender::_renderPass2(Channels<0> chans, const Eigen::Matrix4d &t) {
 	}
 }
 
+void CUDARender::cancel() {
+	out_ = nullptr;
+	scene_ = nullptr;
+	stage_ = Stage::Finished;
+	cudaSafeCall(cudaStreamSynchronize(stream_));
+}
+
 void CUDARender::begin(ftl::rgbd::Frame &out, ftl::codecs::Channel chan) {
 	if (stage_ != Stage::Finished) {
 		throw FTL_Error("Already rendering");
diff --git a/components/streams/src/renderers/openvr_render.cpp b/components/streams/src/renderers/openvr_render.cpp
index 386c8b6aa580fbc746f14b757b1d3ec7c9b23607..2a23beb3e8b305dbd395c9dcb43215c4d22904b2 100644
--- a/components/streams/src/renderers/openvr_render.cpp
+++ b/components/streams/src/renderers/openvr_render.cpp
@@ -448,6 +448,9 @@ bool OpenVRRender::retrieve(ftl::data::Frame &frame_out) {
 			renderer2_->end();
 		} catch (const ftl::exception &e) {
 			LOG(ERROR) << "Render exception: " << e.what();
+			renderer_->cancel();
+			renderer2_->cancel();
+			frame_out.message(ftl::data::Message::Error_RENDER, e.what());
 		}
 
 		if (!post_pipe_) {
diff --git a/components/streams/src/renderers/screen_render.cpp b/components/streams/src/renderers/screen_render.cpp
index 36da28dac57b9b30d855a1a1d35e3af35e6ad56a..3df19e7a387d0aa48fd5a7abe5d07e61cc7819de 100644
--- a/components/streams/src/renderers/screen_render.cpp
+++ b/components/streams/src/renderers/screen_render.cpp
@@ -206,6 +206,8 @@ bool ScreenRender::retrieve(ftl::data::Frame &frame_out) {
 			if (!data_only) renderer_->end();
 		} catch (const ftl::exception &e) {
 			LOG(ERROR) << "Render exception: " << e.what();
+			renderer_->cancel();
+			frame_out.message(ftl::data::Message::Error_RENDER, e.what());
 		}
 
 		if (!data_only) {
diff --git a/components/structures/include/ftl/data/messages.hpp b/components/structures/include/ftl/data/messages.hpp
index 9f90263fd8f3136fedbc91e50e65ec3d55864656..74bcfccb0a8fdfba380b5117dc976a0b75448879 100644
--- a/components/structures/include/ftl/data/messages.hpp
+++ b/components/structures/include/ftl/data/messages.hpp
@@ -13,6 +13,7 @@ enum class Message : int {
 	Error_FRAME_GRAB,
 	Error_BAD_FORMAT,
 	Error_OPENVR,
+	Error_RENDER,
 	Warning_UNKNOWN = 1024,
 	Warning_FRAME_DROP,
 	Warning_PIPELINE_DROP,