diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp
index 0f7575c54b22..c49124290b42 100644
--- a/src/v4l2/v4l2_compat_manager.cpp
+++ b/src/v4l2/v4l2_compat_manager.cpp
@@ -24,6 +24,7 @@
 
 #include <libcamera/camera.h>
 #include <libcamera/camera_manager.h>
+#include <libcamera/property_ids.h>
 
 #include "v4l2_camera_file.h"
 
@@ -113,14 +114,31 @@ int V4L2CompatManager::getCameraIndex(int fd)
 	if (ret < 0)
 		return -1;
 
-	std::shared_ptr<Camera> target = cm_->get(statbuf.st_rdev);
-	if (!target)
-		return -1;
+	const dev_t devnum = statbuf.st_rdev;
 
+	/*
+	 * Iterate each known camera and identify if it reports this nodes
+	 * device number in its list of SystemDevices.
+	 */
 	auto cameras = cm_->cameras();
 	for (auto [index, camera] : utils::enumerate(cameras)) {
-		if (camera == target)
-			return index;
+		const auto devices = camera->properties()
+					     .get(properties::SystemDevices)
+					     .value_or(std::vector<int64_t>{});
+
+		/*
+		 * While there may be multiple Cameras that could reference the
+		 * same device node, we take a first match as a best effort for
+		 * now.
+		 *
+		 * \todo Consider reworking the V4L2 adaptation layer to stop
+		 * trying to map video nodes directly to a camera and instead
+		 * hide all devices that may be used by libcamera and expose a
+		 * consistent 1:1 mapping with each Camera instance.
+		 */
+		for (const int64_t dev : devices)
+			if (dev == static_cast<int64_t>(devnum))
+				return index;
 	}
 
 	return -1;
