A depth or 3D camera that depends on a patched uvcvideo driver only works while that patched module matches the kernel it runs on. Switch the kernel — a downgrade to satisfy another toolchain, an update, a clean install — and modprobe starts answering 'Invalid argument', the patch script aborts, and the viewer finds no camera. This page covers the DKMS side of that failure for engineers building USB depth cameras on Ubuntu: how to read dkms status against uname -r, purge builds and header packages that do not match, rebuild once for the running kernel, and verify the insert. When the patch itself targets the wrong source tree, that is a different defect; start with matching the patch to the source tree.
The rule: a patched module loads only on its own kernel
Every kernel module records a vermagic string: the kernel release and the build flags it was compiled against. With modversions enabled it also stores checksums of the kernel symbols it calls. At insert time the running kernel compares both, and any difference rejects the module — which modprobe prints as 'could not insert uvcvideo: Invalid argument'. A point release counts as a difference: a module built on 4.4.0-114 will not insert on 4.4.0-98, same series or not.
DKMS removes this trap by recompiling each registered module once per installed kernel, as long as that kernel's headers are installed and intact. So the decision rule is short. A patched module that fails to insert after a kernel change is a build-target problem first and a patch problem second: compare dkms status with uname -r before touching anything else.
What the failure looks like
The patch script runs to its final steps and stops:
modprobe: ERROR: could not insert 'uvcvideo': Invalid argument
The script then restores the stock driver and exits, so the machine behaves as if the patch never happened. The capture application lists no device, because the stock uvcvideo lacks the depth-stream handling the camera needs.
The second shape is quieter: the DKMS package itself fails during installation, and the crash log names a DKMSKernelVersion that is not your running release. That single line is usually the whole diagnosis — the package built for one kernel while you booted another. Either way the camera stays dark until a valid build exists for the kernel you actually run.
Four causes, in the order to check them
After a kernel version changes, four causes cover nearly everything, in this order of frequency: stale builds, broken headers, an incomplete package set, and a module still held open by a running process.
| # | Cause | Confirm it with | Fix |
|---|---|---|---|
| 1 | DKMS holds builds only for kernels you no longer run |
dkms status lines against uname -r
|
remove each stale line, then dkms autoinstall
|
| 2 | Header tree of the running kernel is corrupted | make.log shows 'No rule to make target Makefile' | purge and reinstall image, extra and headers |
| 3 | Kernel package set incomplete |
dpkg -l filtered for the release string |
install the missing member of the set |
| 4 | Old uvcvideo still loaded and held open |
lsmod lists uvcvideo when it should not |
close the capture process, rmmod uvcvideo, insert again |
Causes 1 and 3 dominate right after a version switch. Cause 2 appears after an interrupted install or a package operation crash, and it is the expensive one because the build fails without saying why. Cause 4 only bites at reload time, after the build is already correct.
Clean and rebuild: the fix in eight steps
- Fix the reference string. Run
uname -rand write the output down; every later comparison keys off it. On the worked machine below it prints 4.4.0-98-generic. - List what DKMS holds:
dkms status. Each line names a module, a version, a kernel and a state such as installed. - Remove every line whose kernel is not the running one, passing the module and version exactly as the line prints them, with
--all. The worked example writes the command out in full. - Inspect the header tree of the running kernel:
ls -l /usr/src/linux-headers-$(uname -r)/Makefile. A regular file passes; a symlink pointing at itself fails the whole build. - If the tree is broken or a package is missing, purge the set and reinstall it complete — image, extra-drivers package and headers, all three at the same release. The exact package triple for the worked case is in the example below.
- Rebuild for the running kernel:
sudo dkms autoinstall. Watch the compile name youruname -r. - Swap the module:
sudo rmmod uvcvideo 2>/dev/null; sudo modprobe uvcvideo. - Verify.
dkms statusprints the build as installed for the running kernel,lsmodlists uvcvideo,ls /dev/video*shows the camera, and one captured frame proves the depth path end to end.
If step 7 still fails while the status looks correct, the installed file is probably a stale artifact compiled against the broken headers; see the section below on rebuilds that change nothing.
Worked example: downgrading 4.13.0-31 to 4.4.0-98-generic
Inputs, and where each comes from:
- Running kernel, from
uname -r: 4.4.0-98-generic on x86_64. The machine was stepped down to this release for an unrelated toolchain. - Previous kernel, still installed: 4.13.0-31-generic. The camera worked under it before the downgrade.
- Orphaned build target, read from the package failure log's DKMSKernelVersion line: 4.10.0-42-generic.
- Header tree for 4.4.0-98-generic: every file a symlink to itself, confirmed with
ls -land the build log shown below.
Rule in words: the patched module inserts only when DKMS holds a build whose kernel equals the running release, and that build ran against intact headers of the same release.
Arithmetic — compare the version strings:
running 4.4.0-98-generic
build 1 4.10.0-42-generic no match
build 2 4.13.0-31-generic no match
usable builds: 0 of 2
headers for 4.4.0-98-generic: broken
usable header trees: 0 of 1
Zero usable builds over a broken tree: nothing valid can insert, exactly what modprobe reported. The build log names the broken tree:
make: Entering directory '/usr/src/linux-headers-4.4.0-98-generic'
make: Makefile: No such file or directory
make: *** No rule to make target 'Makefile'. Stop.
The fix, in full:
# purge the broken 4.4.0-98 set: image, extra, headers
sudo apt-get --purge remove linux-image-4.4.0-98-generic \
linux-image-extra-4.4.0-98-generic linux-headers-4.4.0-98-generic
# remove stale builds; module and version exactly as dkms status prints them
sudo dkms remove -m uvcvideo/1.1.0 --all
# reboot into the known-good 4.13.0-31-generic, then reinstall the set complete
sudo apt-get install linux-image-4.4.0-98-generic \
linux-image-extra-4.4.0-98-generic linux-headers-4.4.0-98-generic
# boot back into 4.4.0-98-generic, build and load
sudo dkms autoinstall
sudo modprobe uvcvideo
The pair uvcvideo/1.1.0 stands in for the module and version your own dkms status prints; read it from the status line before typing.
Decision and threshold: after the rebuild, dkms status must show exactly one line ending in installed, and its kernel must equal uname -r character for character — here 4.4.0-98-generic. Any other state leaves the camera dark; purge and rebuild again. This machine ends with one build, one kernel, zero mismatches, and the viewer lists the camera.
Corrupted headers: no rule to make target 'Makefile'
A healthy header package gives /usr/src/linux-headers-4.4.0-98-generic (your release substituted) a Makefile, a .config and an include/ tree. When an install is interrupted or a package operation reconfigures the set midway, the tree can end up with files symlinked to themselves: every path resolves to itself, make cannot read the Makefile, and the compile dies with the log shown above.
Two checks take ten seconds. First the log: the failed build's make.log sits in the module's build folder under /var/lib/dkms, and 'No rule to make target Makefile' names the tree that is broken. Second the tree itself: ls -l /usr/src/linux-headers-$(uname -r)/Makefile — when the same name appears on both sides of the arrow, the tree is gone.
Fix it the way the example does: purge and reinstall the whole set for that release. Do not hand-repair individual symlinks; a half-repaired tree compiles further and fails later, which costs more time than the purge. The same philosophy holds when a driver file itself is corrupted: reinstall, don't copy files.
When the rebuild still fails
Work down this list:
-
dkms statusshows a matching line marked installed, the headers are clean, and insert still fails. The installed file predates the header repair — compiled against the broken tree and recorded as done. Remove that module and version with--all, rundkms autoinstallagain, and insert. - Insert fails because the module is in use. Something is capturing from the old driver. Close the application, run
sudo rmmod uvcvideo, then modprobe again. - uvcvideo is absent from
lsmodand /dev/video is empty even for other USB cameras. The driver may be compiled into the kernel rather than built as a module, which modprobe cannot replace; that is a separate defect — see when uvcvideo is built in. - No camera node after a clean insert. The stock driver enumerated the device without its depth interface; work through no video device for a 3D camera on Linux.
- The patch step itself rejects hunks or cannot find files. The patch targets another source tree, not the kernel pairing; the fix-or-skip decision for a failed depth-camera kernel patch and the source-tree check when the patch cannot find its file cover that path.
Prevent it on the next kernel switch
- Install the kernel and its headers in one command. A set that arrives in separate operations is what produced the broken tree above.
- Run
sudo dkms autoinstallafter every kernel install or removal, before rebooting into it. - Keep only kernels you actually boot. The worked machine carried three — 4.4.0-98, 4.10.0-42 and 4.13.0-31 — and two were dead weight that made
dkms statushard to read. - Write the reason next to any downgrade. This case stepped back to 4.4.0-98 for an unrelated toolchain, and the next package operation broke the pairing silently.
- If the station must run today and the rebuild can wait until tomorrow, rolling back the patched driver after failed attempts returns the machine to the stock module cleanly.
Checklist before you reboot
Before purging anything:
-
uname -rwritten down — every comparison keys off this exact string. -
dkms statusoutput saved — it names the stale builds and their module and version pairs. - A known-good kernel confirmed in the boot menu — purge only a release you can afford to lose.
After rebuilding:
- One line in
dkms statusends in installed and its kernel equalsuname -r— the threshold from the worked example. -
lsmodlists uvcvideo — the patched module is the one loaded, not a leftover. -
ls /dev/video*shows the camera node — enumeration succeeded. - One frame captured in your own application — the depth path works end to end.
If the sequence still ends in Invalid argument, send the make.log and the dkms status output through the contact page — free expert support comes with every order. To skip patched drivers entirely, browse 3D sensors with native SDK support or filter the camera finder by interface and depth type; the same integration questions apply across area scan cameras, and the 3D topic page collects the depth-camera integration notes.
Questions
Why does modprobe report Invalid argument instead of a version mismatch?
The module loader checks vermagic and symbol checksums at insert time and returns the error code that maps to Invalid argument; the human-readable reason lands in the kernel log, not on the modprobe line. Treat the message as one thing only: the file in that module directory was not built for the kernel now running. dmesg captured at insert time shows the exact complaint.
How can I check which kernel an existing module file was built for?
Run modinfo on the file and read the vermagic line: modinfo uvcvideo piped through grep vermagic prints the kernel release the module was compiled against, plus flags such as SMP and mod_unload. Compare that release string with the output of uname -r; any difference, even only in the point release, means the file belongs to another kernel and must be rebuilt.
Can two patched kernels stay installed at the same time?
Yes. DKMS keeps one build directory per kernel, so a machine that boots between two releases can hold a patched module for each, provided the header packages of both versions are installed and intact. Only the build for the running kernel can insert, though. After switching kernels, run dkms autoinstall once so the new release gets its own build before you modprobe.
Does dkms remove delete the patch source?
No. dkms remove clears the build directory under /var/lib/dkms and the compiled module file for the kernels you name. The patch source stays where the package put it, in /usr/src inside the module-version folder, so a later dkms autoinstall rebuilds from the same patch. Delete that source folder only when you want the patch gone for good.
Is it safe to purge the kernel packages of the release I am running?
Not while you are booted into it, unless you can reboot immediately afterwards: purging the image removes that kernel from the boot menu at the next restart. The safe order is to confirm a known-good kernel is still installed, reboot into it, then purge the broken version's image, extra-drivers and header packages and reinstall the set completely. The worked example above follows exactly that order.