diff --git a/src/libcamera/control_ids_rpi.yaml b/src/libcamera/control_ids_rpi.yaml
index 0b7da5b..5348060 100644
--- a/src/libcamera/control_ids_rpi.yaml
+++ b/src/libcamera/control_ids_rpi.yaml
@@ -192,4 +192,15 @@ controls:
         just been applied. Controls normally take several frames to apply,
         so the number here will refer to a request submitted a number of
         frames earlier.
+
+  - SensorSequence:
+      type: int64_t
+      direction: out
+      description: |
+        Monotonic frontend/Unicam sequence number for the sensor frame.
+
+        Any break in this sequence number indicates that frames were not
+        captured into the frontend stream before this request completed. This
+        value is Raspberry Pi pipeline metadata and is intended for diagnostics
+        of sensor-side frame continuity.
 ...
diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
index 5a5acf6..22327bd 100644
--- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
+++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
@@ -1516,6 +1516,8 @@ void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request
 		request->_d()->metadata().set(controls::SensorTimestamp, *x);
 	if (auto x = bufferControls.get(controls::FrameWallClock))
 		request->_d()->metadata().set(controls::FrameWallClock, *x);
+	if (auto x = bufferControls.get(controls::rpi::SensorSequence))
+		request->_d()->metadata().set(controls::rpi::SensorSequence, *x);
 
 	if (cropParams_.size()) {
 		std::vector<Rectangle> crops;
diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
index 3e9a490..0f437b2 100644
--- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
@@ -777,16 +777,18 @@ void Vc4CameraData::unicamBufferDequeue(FrameBuffer *buffer)
 		 */
 		auto [ctrl, delayContext] = delayedCtrls_->get(buffer->metadata().sequence);
 		/*
-		 * Add the frame timestamp to the ControlList for the IPA to use
-		 * as it does not receive the FrameBuffer object. Also derive a
-		 * corresponding wallclock value.
+		 * Add the frame timestamp and sequence number to the ControlList
+		 * for the IPA to use as it does not receive the FrameBuffer object.
+		 * Also derive a corresponding wallclock value.
 		 */
 		wallClockRecovery_.addSample();
 		uint64_t sensorTimestamp = buffer->metadata().timestamp;
 		uint64_t wallClockTimestamp = wallClockRecovery_.getOutput(sensorTimestamp);
+		unsigned int sensorSequence = buffer->metadata().sequence;
 
 		ctrl.set(controls::SensorTimestamp, sensorTimestamp);
 		ctrl.set(controls::FrameWallClock, wallClockTimestamp);
+		ctrl.set(controls::rpi::SensorSequence, sensorSequence);
 		bayerQueue_.push({ buffer, std::move(ctrl), delayContext });
 	} else {
 		embeddedQueue_.push(buffer);
