diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index a0ea138d9499..0ce9b699bfae 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -244,7 +244,7 @@ CameraDevice::Camera3RequestDescriptor::Camera3RequestDescriptor(
 	 * Create the CaptureRequest, stored as a unique_ptr<> to tie its
 	 * lifetime to the descriptor.
 	 */
-	request_ = std::make_unique<CaptureRequest>(camera);
+	request_ = std::make_unique<CaptureRequest>(camera, camera3Request);
 }
 
 /*
@@ -264,6 +264,7 @@ CameraDevice::CameraDevice(unsigned int id, std::shared_ptr<Camera> camera)
 	: id_(id), state_(State::Stopped), camera_(std::move(camera)),
 	  facing_(CAMERA_FACING_FRONT), orientation_(0)
 {
+	worker_.requestQueueFailed.connect(this, &CameraDevice::requestQueueFailed);
 	camera_->requestCompleted.connect(this, &CameraDevice::requestComplete);
 
 	maker_ = "libcamera";
@@ -1060,6 +1061,25 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
 	return 0;
 }
 
+void CameraDevice::requestQueueFailed(CaptureRequest *request)
+{
+	/*
+	 * Remove the descriptor from the map if the worker has failed
+	 * to process it and notify the camera service about the failure.
+	 */
+	MutexLocker descriptorsLock(descriptorsMutex_);
+	auto it = descriptors_.find(request->cookie());
+	if (it == descriptors_.end()) {
+		LOG(HAL, Fatal)
+			<< "Unknown request: " << request->cookie();
+		return;
+	}
+
+	descriptors_.extract(it);
+
+	abortRequest(request->camera3Request());
+}
+
 void CameraDevice::requestComplete(Request *request)
 {
 	decltype(descriptors_)::node_type node;
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index 54c4cb9ab499..65456ecca7e3 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -83,6 +83,7 @@ private:
 		std::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;
 		CameraMetadata settings_;
 		std::unique_ptr<CaptureRequest> request_;
+		const camera3_capture_request_t *camera3Request_;
 	};
 
 	enum class State {
diff --git a/src/android/camera_worker.cpp b/src/android/camera_worker.cpp
index 98dddd9eb13b..7f39fab01638 100644
--- a/src/android/camera_worker.cpp
+++ b/src/android/camera_worker.cpp
@@ -27,8 +27,9 @@ LOG_DECLARE_CATEGORY(HAL)
  * by the CameraWorker which queues it to the libcamera::Camera after handling
  * fences.
  */
-CaptureRequest::CaptureRequest(libcamera::Camera *camera)
-	: camera_(camera)
+CaptureRequest::CaptureRequest(libcamera::Camera *camera,
+			       const camera3_capture_request_t *camera3Request)
+	: camera_(camera), camera3Request_(camera3Request)
 {
 	request_ = camera_->createRequest(reinterpret_cast<uint64_t>(this));
 }
@@ -77,7 +78,7 @@ void CameraWorker::queueRequest(CaptureRequest *request)
 {
 	/* Async process the request on the worker which runs its own thread. */
 	worker_.invokeMethod(&Worker::processRequest, ConnectionTypeQueued,
-			     request);
+			     this, request);
 }
 
 /*
@@ -109,7 +110,7 @@ int CameraWorker::Worker::waitFence(int fence)
 	return -errno;
 }
 
-void CameraWorker::Worker::processRequest(CaptureRequest *request)
+void CameraWorker::Worker::processRequest(CameraWorker *context, CaptureRequest *request)
 {
 	/* Wait on all fences before queuing the Request. */
 	for (int fence : request->fences()) {
@@ -121,6 +122,7 @@ void CameraWorker::Worker::processRequest(CaptureRequest *request)
 		if (ret < 0) {
 			LOG(HAL, Error) << "Failed waiting for fence: "
 					<< fence << ": " << strerror(-ret);
+			context->requestQueueFailed.emit(request);
 			return;
 		}
 	}
diff --git a/src/android/camera_worker.h b/src/android/camera_worker.h
index 67ae50bd9288..86f20f741e54 100644
--- a/src/android/camera_worker.h
+++ b/src/android/camera_worker.h
@@ -10,6 +10,7 @@
 #include <memory>
 
 #include <libcamera/base/object.h>
+#include <libcamera/base/signal.h>
 #include <libcamera/base/thread.h>
 
 #include <libcamera/camera.h>
@@ -22,7 +23,8 @@ class CameraDevice;
 class CaptureRequest
 {
 public:
-	CaptureRequest(libcamera::Camera *camera);
+	CaptureRequest(libcamera::Camera *camera,
+		       const camera3_capture_request_t *camera3Request);
 
 	const std::vector<int> &fences() const { return acquireFences_; }
 	libcamera::ControlList &controls() { return request_->controls(); }
@@ -31,6 +33,7 @@ public:
 		return request_->metadata();
 	}
 	unsigned long cookie() const { return request_->cookie(); }
+	const camera3_capture_request_t *camera3Request() const { return camera3Request_; }
 
 	void addBuffer(libcamera::Stream *stream,
 		       libcamera::FrameBuffer *buffer, int fence);
@@ -40,6 +43,7 @@ private:
 	libcamera::Camera *camera_;
 	std::vector<int> acquireFences_;
 	std::unique_ptr<libcamera::Request> request_;
+	const camera3_capture_request_t *camera3Request_;
 };
 
 class CameraWorker : private libcamera::Thread
@@ -51,6 +55,7 @@ public:
 	void stop();
 
 	void queueRequest(CaptureRequest *request);
+	libcamera::Signal<CaptureRequest *> requestQueueFailed;
 
 protected:
 	void run() override;
@@ -59,7 +64,7 @@ private:
 	class Worker : public libcamera::Object
 	{
 	public:
-		void processRequest(CaptureRequest *request);
+		void processRequest(CameraWorker *context, CaptureRequest *request);
 
 	private:
 		int waitFence(int fence);
