diff --git a/include/libcamera/internal/delayed_controls.h b/include/libcamera/internal/delayed_controls.h
index e2decbcc..91c9415a 100644
--- a/include/libcamera/internal/delayed_controls.h
+++ b/include/libcamera/internal/delayed_controls.h
@@ -67,6 +67,8 @@ private:
 		{
 			return std::array<Info, listSize>::operator[](index % listSize);
 		}
+
+		unsigned int largestValidIndex;
 	};
 
 	bool controlsAreQueued(unsigned int frame, const ControlList &controls);
diff --git a/src/libcamera/delayed_controls.cpp b/src/libcamera/delayed_controls.cpp
index 3fd5a0f7..7f2bb479 100644
--- a/src/libcamera/delayed_controls.cpp
+++ b/src/libcamera/delayed_controls.cpp
@@ -151,6 +151,7 @@ void DelayedControls::reset(ControlList *controls)
 		 * to be written to to device on startup.
 		 */
 		values_[id][0] = Info(ctrl.second, 0, false);
+		values_[id].largestValidIndex = 0;
 	}
 
 	/* Propagate initial state */
@@ -304,18 +305,34 @@ bool DelayedControls::push(const ControlList &controls, std::optional<uint32_t>
 			continue;
 		}
 
-		Info &info = values_[id][updateIndex];
+		ControlRingBuffer &ring = values_[id];
+		Info &info = ring[updateIndex];
 		/*
 		 * Update the control only if the already existing value stems from a
 		 * request with a sequence number smaller or equal to the current one
 		 */
 		if (info.sourceSequence <= sequence) {
 			info = Info(control.second, sequence);
+			if (updateIndex > ring.largestValidIndex)
+				ring.largestValidIndex = updateIndex;
 
 			LOG(DelayedControls, Debug)
 				<< "Queuing " << id->name()
 				<< " to " << info.toString()
 				<< " at index " << updateIndex;
+
+			/* fill up the next indices with the new information */
+			unsigned int i = updateIndex + 1;
+			while (i <= ring.largestValidIndex) {
+				LOG(DelayedControls, Error) << "update " << i;
+				Info &next = ring[i];
+				if (next.sourceSequence <= sequence)
+					next = info;
+				else
+					break;
+
+				i++;
+			}
 		} else {
 			LOG(DelayedControls, Warning)
 				<< "Skipped update " << id->name()
diff --git a/test/delayed_controls.cpp b/test/delayed_controls.cpp
index 481334e7..7d671a0e 100644
--- a/test/delayed_controls.cpp
+++ b/test/delayed_controls.cpp
@@ -271,6 +271,68 @@ protected:
 		return TestPass;
 	}
 
+	int updateTooLateMustSometimesBeIgnored()
+	{
+		std::unordered_map<uint32_t, DelayedControls::ControlParams> delays = {
+			{ V4L2_CID_BRIGHTNESS, { 2, false } },
+		};
+		std::unique_ptr<DelayedControls> delayed =
+			std::make_unique<DelayedControls>(dev_.get(), delays);
+		ControlList ctrls;
+
+		/* Reset control to value that will be first in test. */
+		int32_t initial = 4;
+		ctrls.set(V4L2_CID_BRIGHTNESS, initial);
+		dev_->setControls(&ctrls);
+		delayed->reset();
+
+		int32_t expected = 10;
+
+		delayed->push({}, 0);
+		delayed->push({}, 1);
+		ctrls.set(V4L2_CID_BRIGHTNESS, expected);
+		delayed->push(ctrls, 2);
+		delayed->applyControls(0); /* puts 10 on the bus */
+
+		/*
+		 * Post an update for frame 1. It's too late to fulfill that request,
+		 * delayed controls will therefore try to delay it to frame 3. But as
+		 * frame 2 is already queued, the update must be dropped.
+		 */
+		ctrls.set(V4L2_CID_BRIGHTNESS, 20);
+		delayed->push(ctrls, 1);
+		delayed->applyControls(1);
+		delayed->applyControls(2);
+		delayed->applyControls(3);
+
+		int frame = 3;
+
+		ControlList result = delayed->get(frame);
+		int32_t brightness = result.get(V4L2_CID_BRIGHTNESS).get<int32_t>();
+		ControlList ctrlsV4L = dev_->getControls({ V4L2_CID_BRIGHTNESS });
+		int32_t brightnessV4L = ctrlsV4L.get(V4L2_CID_BRIGHTNESS).get<int32_t>();
+
+		if (brightness != expected) {
+			cerr << "Failed " << __func__
+			     << " frame " << frame
+			     << " expected " << expected
+			     << " got " << brightness
+			     << endl;
+			return TestFail;
+		}
+
+		if (brightnessV4L != expected) {
+			cerr << "Failed " << __func__
+			     << " frame " << frame
+			     << " expected V4L " << expected
+			     << " got " << brightnessV4L
+			     << endl;
+			return TestFail;
+		}
+
+		return TestPass;
+	}
+
 	int updateTooLateGetsDelayed()
 	{
 		std::unordered_map<uint32_t, DelayedControls::ControlParams> delays = {
@@ -503,6 +565,10 @@ protected:
 		if (ret)
 			failed = true;
 
+		ret = updateTooLateMustSometimesBeIgnored();
+		if (ret)
+			failed = true;
+
 		ret = updateTooLateGetsDelayed();
 		if (ret)
 			failed = true;
