You ran dmesg, the kernel prints Detected IMX219 sensor, and libcamera still answers no cameras available. That combination is common on embedded Linux bring-ups, and it is better news than it looks: power, wiring and the I2C link are already proven, so only three stages remain to check. This guide gives you the four-stage check that names the broken stage in minutes, the fix for each stage, the arithmetic that shows why lane counts are rarely the culprit once the probe succeeds, and the point at which moving the capture to a supported industrial camera module becomes the cheaper decision.
Why does dmesg detect the sensor while libcamera lists no cameras?
Because a successful I2C probe is only the first of four stages: the sensor driver must bind, the CSI-2 receiver must instantiate, a media graph with a /dev/media node must appear, and only then does libcamera's pipeline handler list a camera device. The probe line proves stage 1 passed; the empty list tells you one of the other three failed, usually without printing an error of its own.
The four stages, each with its own trace:
- Sensor driver binds over I2C. The overlay instantiates the sensor, the driver reads its ID register, and the kernel prints the probe lines.
- CSI-2 receiver instantiates. The receiver driver (unicam on the common SoC families) needs its own node from the same overlay set.
- Media graph registers. Sensor and receiver bound together create the media-controller node /dev/media0 and the capture node /dev/video0 under it.
- libcamera composes a camera. The pipeline handler walks the graph, matches the sensor and loads its tuning data; only then does --list-cameras print anything.
The later stages fail silently: no error line, just a missing node. That is why the log looks healthy while the camera list stays empty. When the symptom is instead no probe line at all, start with the image sensor not detected guide and the camera I2C communication failure guide, because the fault sits one stage earlier.
What does the Detected IMX219 sensor line actually prove?
Exactly three things: the overlay instantiated the sensor on a bus, the module answered at its address, and the driver read and matched the sensor's ID — nothing about the data lanes, the media pipeline or libcamera. It is an I2C-level proof only, which is why it can sit alongside an empty camera list without contradiction.
Decode the line you have:
imx219 10-0010: probing IMX219 sensor
imx219 10-0010: Detected IMX219 sensor
The text before the colon names driver, bus and device: the imx219 driver, on I2C adapter 10, at device address 0x0010. The address belongs to the sensor hardware — an IMX219-class part answers at 0x10 — and the overlay simply has to declare the same one. Two consequences follow:
- If the line prints, the driver you loaded is physically talking to your module, so the ribbon, connector and power are good.
- If the driver name or address does not match the module you bought, the overlay is loading for the wrong part. The wrong sensor driver guide shows how to read that mismatch out of the log.
What does the motorized focus warning in dmesg mean?
It means the module on the cable is a motorized-focus variant, and its lens actuator has a control path that the generic sensor overlay does not set up, so the sensor probes cleanly but the variant's pipeline can never be completed.
Many modules ship in two variants with the same sensor: a fixed-focus part and a motorized-focus part whose lens actuator hangs off the same I2C bus. The generic sensor overlay instantiates the sensor and nothing else; the actuator needs its own driver node, and the variant is fully supported only through the overlay and driver package the module vendor documents for it.
The warning is therefore the most valuable line in the log: it identifies the module as the variant, not the base part. The fix is not a tweak to dtoverlay=imx219; it is installing exactly the overlay and driver package the vendor documents for that variant, on your board family and OS release. With camera_auto_detect=0 in /boot/config.txt, nothing selects a variant overlay for you, so the generic line stays until you change it. If the vendor publishes no Linux stack for the variant, treat the module as unsupported on this platform: no overlay edit completes the graph, and the supported-module section below is the exit.
Which stage is broken, and how do I test each one?
Run the four checks below in order; the first one that fails names the broken stage — dmesg probe, /dev/media node, /dev/video capture node, libcamera --list-cameras.
-
Probe lines. Run
dmesg | grep imx; if empty, widen it withdmesg | grep -iE 'imx219|unicam|csi'. No line at all points at the overlay name, the port or the ribbon. -
Media-controller node. Run
ls -l /dev/media*. A probe line with no media node means the CSI-2 receiver never instantiated — an incomplete overlay set for the board family. The devicetree chain guide walks that exact break. -
Capture node. Run
ls -l /dev/video*andv4l2-ctl --list-devices. A media node with no capture node means the receiver bound but the capture side failed; read the full dmesg tail for the driver's complaint and compare the overlay against the device tree mismatch guide. -
Camera list. Run
libcamera-hello --list-cameras(the same flag works onlibcamera-still). Nodes present but the list empty points at the userspace stack, covered in the next section.
| dmesg probe | /dev/media* | /dev/video* | libcamera list | Broken stage | Fix first |
|---|---|---|---|---|---|
| none | none | none | none | Overlay, port or wiring | Overlay name, cable seat, I2C link |
| present | none | none | none | Receiver never instantiated | Overlay set for the board family |
| present | present | none | none | Capture node missing | Driver and overlay match; full log tail |
| present | present | present | none | Userspace stack | Stack update, tuning data, permissions |
| present | present | present | listed | Working | Add the variant's actuator support if the warning prints |
Ranked by how often each is the culprit once the probe prints: the variant overlay first, a missing receiver node second, an outdated userspace stack third, permissions or container isolation fourth, lane mismatch last — lanes usually kill the probe itself, as the next section explains.
What does a healthy bring-up look like, node by node?
On a single-camera board a healthy chain leaves exactly one media-controller node, one capture node and a two-entity graph: your sensor subdev linked to the CSI-2 receiver, and nothing else.
With one module connected, media-ctl -d /dev/media0 -p should print the sensor subdev, named for its driver and bus address, linked to the receiver, and v4l2-ctl --list-devices groups the capture node under the receiver's entry. Two camera ports give two of each, and the bus index in each probe line tells you which module is which.
Worth a second look: a sensor entity with no link to the receiver, a receiver with no capture node beneath it, or media nodes numbered above zero with only one camera connected — each means the graph did not complete. Entity names shift slightly between kernel releases; the shape, sensor to receiver to capture, does not.
Do MIPI data lanes matter once the probe has succeeded?
Rarely at this stage: the probe ran over I2C, but the lanes decide whether a stream can start — a two-lane module declared as four lanes in the overlay probes fine and then never delivers frames.
The lane count lives in the overlay as a data-lanes setting and must match the module. Declaring four lanes for a two-lane part fails earlier in the chain — the probe itself — so lane mismatches belong to the no-probe symptom, not this one; the two-lane and four-lane mode guide covers that case. Once the probe prints, the arithmetic shows why lanes are rarely the blocker. A full-resolution RAW10 stream from this sensor class runs 3280 × 2464 pixels at 15 frames per second:
Add roughly 6-8% for packet overhead and each lane carries about 0.65 Gbit/s, inside the roughly 1 Gbit/s per lane that first-generation MIPI D-PHY links are rated for. Two lanes carry this stream by design, so do not widen the overlay to four lanes hoping to fix an empty camera list — the module will simply stop probing.
Does the userspace stack itself ever cause the empty list?
Yes, and it is the cause behind many dead-end hunts: a capture stack older than the sensor's support, a missing tuning file, or a session without permission to open the media nodes all return no cameras on a kernel side that is perfect.
- An old capture stack. libcamera and its applications predate newer sensors and pipeline features; the fix is updating the OS packages to the current release, not more overlay edits.
- Missing tuning data. The pipeline handler composes a camera only when it can match the sensor and load its tuning; without it the sensor can sit in /dev with a healthy graph while the list stays empty. The application output usually names the file or the sensor it could not match.
- Permissions and isolation. A session outside the group that owns /dev/video* and /dev/media* sees the nodes but cannot open them; the device permission checks guide gives the exact tests. In a container, pass the media nodes as well as the video nodes, as the container V4L2 media node guide shows.
When every node exists and the stack is current, --list-cameras either lists the camera or prints a warning naming what is missing. At that point the log decides, not guesswork.
When should I stop debugging and move the capture to a supported module?
When the vendor publishes no Linux driver or overlay for your exact variant, the fastest engineering decision is to move the capture to a module that enumerates over USB3 or GigE, because those interfaces need no overlay, no media graph and no tuning file.
The trade is concrete. A MIPI board camera needs five things to exist for your exact variant, board family and OS release — sensor overlay, receiver node, media graph, tuning file, actuator driver — and none of them is visible from the outside. A USB3 or GigE module enumerates through its interface with a vendor capture stack, so bring-up becomes an SDK install and a configuration file.
Switch when the vendor publishes no Linux stack for the variant, when a distribution update you cannot pin keeps breaking the pipeline, or when the project needs a supported image more than it needs a ribbon connector. If that is the decision, the board-level range below does the same job over standard interfaces:
- Sensor format
- 1/1.8"
- Lens mount
- C-mount
- Sensor format
- 1/2.9"
- Lens mount
- M12
- Sensor format
- 1/1.8"
- Lens mount
- CS-mount
The LS-BCM-0003 is a 3.1 MP USB3 board-level camera with a global shutter, specified at 120 fps. The MV-CB016-10GM-M-W is a 1.6 MP GigE module with an M12 lens mount and a global shutter. The LS-BCM-0020 covers 6.3 MP over GigE at 18 fps through a CS-mount.
Browse the board-level cameras or the camera finder, or start from your resolution and interface in the camera configurator; the board level camera selection guide covers the format and interface trade-offs in detail.
How do I keep the fix in place after the next kernel update?
Record the exact stack that worked — overlay lines, package versions, kernel release — because a distribution kernel update can silently break the media pipeline while the I2C probe still succeeds, and a recorded baseline turns that from a two-day hunt into a two-minute diff.
This failure mode is real: a distribution kernel update in July 2025 broke IMX219 enumeration in the media pipeline on a popular board family while the probe still succeeded, and it was reported upstream against that release. Keep the baseline in four places:
- The exact /boot/config.txt camera lines, in version control, with a comment naming the module variant.
- The kernel release and capture-stack package versions captured beside them.
- The four-stage check scripted — probe grep, node listing, camera list — and run after every update before the board ships.
- The previous kernel package kept installed, so a regression costs a boot choice rather than a rebuild.
A driver that loads for the wrong variant after an update shows the same signature as a fresh mismatch, so the mismatch guides linked above stay relevant long after bring-up.
If you want a second opinion on a bring-up log, or a module whose stack is supported out of the box, the applications team reads bring-up logs sent through the contact page. The systems topic page collects the rest of the bring-up guides, from probe failures to streaming faults.
Questions
Could a weak power supply alone cause this symptom?
Unlikely on its own. An undervoltage board usually prints its own dmesg warning and often drops the I2C probe entirely, so no sensor line appears at all. Swap supplies and cables only when the probe line is missing; when it prints and the media node is missing, the overlay, not power, decides.
Does a /dev/video0 node mean libcamera should list the camera?
No. The capture node only proves a driver bound. libcamera additionally needs the complete media graph, a pipeline handler that recognizes the sensor, and the sensor's tuning data before it reports a camera. Raw V4L2 capture can therefore work at the node while --list-cameras still prints no cameras available.
Can two modules with the same sensor share one camera port?
Not on one port. Both modules answer at the same I2C address — 0x10 on an IMX219-class sensor — so only the first probes and the second stays invisible. Give each module its own camera port and overlay line, and tell them apart afterwards by the bus index in each probe line.
Does the same fix apply to a fixed-focus module with the same sensor?
Yes for the four-stage check, and usually the generic sensor overlay is then enough, because there is no actuator to bring up. If the media node exists and the list stays empty, look at the userspace side first: package age, tuning data and group permissions cause most of those cases.
Why does the camera list stay empty inside a container?
A container sees only the device files you pass through. Media and capture nodes are separate files, and libcamera needs both plus matching group permissions to build a pipeline; passing only /dev/video0 leaves the graph invisible inside the container and the list empty.


