diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index 2d0a80664214..75a21008070b 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -713,9 +713,14 @@ Request *Camera::createRequest()
  * \brief Queue a request to the camera
  * \param[in] request The request to queue to the camera
  *
- * This method queues a \a request allocated with createRequest() to the camera
- * for capture. Once the request has been queued, the camera will notify its
- * completion through the \ref requestCompleted signal.
+ * This method queues a \a request to the camera for capture.
+ *
+ * After allocating the request with createRequest(), the application shall
+ * fill it with at least one capture buffer before queuing it. Requests that
+ * contain no buffers are invalid and are rejected without being queued.
+ *
+ * Once the request has been queued, the camera will notify its completion
+ * through the \ref requestCompleted signal.
  *
  * Ownership of the request is transferred to the camera. It will be deleted
  * automatically after it completes.
diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
index e5c25d2c6988..502048683245 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -115,7 +115,12 @@ Buffer *Request::findBuffer(Stream *stream) const
  */
 
 /**
- * \brief Prepare the resources for the completion handler
+ * \brief Validate the request and prepare it for the completion handler
+ *
+ * Requests that contain no buffers are invalid and are rejected.
+ *
+ * \return 0 on success or a negative error code otherwise
+ * \retval -EINVAL The request is invalid
  */
 int Request::prepare()
 {
@@ -124,6 +129,11 @@ int Request::prepare()
 		pending_.insert(buffer);
 	}
 
+	if (!hasPendingBuffers()) {
+		LOG(Request, Error) << "Invalid request due to missing buffers";
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
