diff --git a/applications/gui2/src/modules/calibration/calibration.hpp b/applications/gui2/src/modules/calibration/calibration.hpp
index de90a46f03df3ad7b89426093f7817fb3de9ca67..e2e45e9e43528c27ed1fb8676f69611f3acb2812 100644
--- a/applications/gui2/src/modules/calibration/calibration.hpp
+++ b/applications/gui2/src/modules/calibration/calibration.hpp
@@ -19,9 +19,10 @@ public:
 	void set(unsigned int flag) { flags_ |= flag; }
 	void unset(unsigned int  flag) { flags_ &= ~flag; }
 	void reset() { flags_ = 0; }
+	std::string name(int) const;
+
 	int defaultFlags() const;
 	std::vector<int> list() const;
-	std::string name(int) const;
 	std::string explain(int) const;
 	operator int() { return flags_; }
 
@@ -36,8 +37,6 @@ public:
 	std::string explain(int) const;
 };
 
-
-
 /**
  * Calibration. Loads Intrinsic and Extrinsic calibration modules and
  * adds buttons to main screen.
@@ -313,6 +312,8 @@ private:
 
 	std::future<void> future_;
 	std::mutex mtx_;
+	ftl::data::FrameSetPtr fs_current_;
+	ftl::data::FrameSetPtr fs_update_;
 
 	struct State {
 		cv::Mat gray_left;
@@ -328,10 +329,9 @@ private:
 		float last = 0.0f;
 		float frequency = 0.5f;
 		int count = 0;
+		float reprojection_error = NAN;
 		OpenCVCalibrateFlagsStereo flags;
 
-		ftl::data::FrameSetPtr fs_current;
-		ftl::data::FrameSetPtr fs_updated;
 		ftl::data::FrameSetPtr fs_previous_points;
 		std::vector<std::vector<cv::Point2f>> points_l;
 		std::vector<std::vector<cv::Point2f>> points_r;
diff --git a/applications/gui2/src/modules/calibration/stereo.cpp b/applications/gui2/src/modules/calibration/stereo.cpp
index 29fd3a9ea11f9134df0b2d7400195cd6aa920486..9d00eca149caf539193cac190bed5479dfd2c48d 100644
--- a/applications/gui2/src/modules/calibration/stereo.cpp
+++ b/applications/gui2/src/modules/calibration/stereo.cpp
@@ -135,6 +135,7 @@ bool StereoCalibration::onFrame_(const ftl::data::FrameSetPtr& fs) {
 	auto& frame = fs->frames[state_->id.source()];
 
 	if (!checkFrame(frame)) { return true; }
+	if (!frame.hasAll({channelLeft_(), channelRight_()})) { return true; }
 	if (!state_->capture) { return true; }
 	if ((float(glfwGetTime()) - state_->last) < state_->frequency) { return true; }
 	if (state_->running.exchange(true)) { return true; }
@@ -143,8 +144,10 @@ bool StereoCalibration::onFrame_(const ftl::data::FrameSetPtr& fs) {
 
 		try {
 			auto& frame = (*fs)[state_->id.source()].cast<ftl::rgbd::Frame>();
-			cv::cvtColor(getMat(frame, channelLeft_()), state_->gray_left, cv::COLOR_BGRA2GRAY);
-			cv::cvtColor(getMat(frame, channelRight_()), state_->gray_right, cv::COLOR_BGRA2GRAY);
+			auto l = getMat(frame, channelLeft_());
+			auto r = getMat(frame, channelRight_());
+			cv::cvtColor(l, state_->gray_left, cv::COLOR_BGRA2GRAY);
+			cv::cvtColor(r, state_->gray_right, cv::COLOR_BGRA2GRAY);
 
 			std::vector<cv::Point2d> pointsl;
 			std::vector<cv::Point2d> pointsr;
@@ -203,8 +206,10 @@ bool StereoCalibration::isBusy() {
 }
 
 void StereoCalibration::run() {
+	if (state_->running) { return; }
+	
 	state_->running = true;
-	future_ = ftl::pool.push([this](int id) {
+	future_ = ftl::pool.push([this](int) {
 		try {
 			auto& calib_l = state_->calib.get(Channel::Left);
 			auto& calib_r = state_->calib.get(Channel::Right);