On an embedded board, Invalid module format most often means the module was built against a kernel tree whose release string or configuration differs from the kernel that is running. The tool’s message carries only an error number. The kernel log usually names the exact check that rejected the file, so the first thing to do is run dmesg immediately after the failed load and read the last line.
The message
insmod: ERROR: could not insert module mydriver.ko: Invalid module formatThe text Invalid module format is not printed by the kernel. It comes from mod_strerror() in tools/insmod.c of kmod, which translates the error number ENOEXEC returned by the finit_module() or init_module() system call. The kernel’s module loader returns -ENOEXEC from many places in load_module() and the functions it calls, in kernel/module/main.c, so the message says only that the loader refused the file. Other tools print the same error number in different words:
modprobe: ERROR: could not insert 'mydriver': Exec format error
insmod: can't insert 'mydriver.ko': invalid module formatThe first line is kmod’s modprobe, which passes ENOEXEC to strerror(). The second is the BusyBox insmod applet, whose moderror() table uses lower case. The diagnosis below applies to all three forms.
Quick diagnosis: which Invalid module format cause you have
Load the module once more and read the kernel log:
root@imx8mp-evk:~# insmod mydriver.ko
root@imx8mp-evk:~# dmesg | tail| Cause | How to confirm | Fix |
|---|---|---|
| 1. Version magic differs | dmesg shows version magic '...' should be '...' | Rebuild against the running kernel’s build tree and configuration |
2. module_layout checksum differs | dmesg shows disagrees about version of symbol module_layout | Rebuild against the tree and Module.symvers of the running kernel |
| 3. Wrong architecture, compressed or damaged file | readelf -h mydriver.ko on the build host; dmesg shows an Invalid ELF header or Invalid architecture line | Cross-compile for the board, decompress, or copy the file again |
4. struct module size differs | dmesg shows section size must match the kernel's built struct module size at run time | Rebuild with the running kernel’s configuration |
| 5. Module carries no symbol versions | dmesg shows nothing; readelf -S mydriver.ko lists no __versions section | Build against a tree configured with CONFIG_MODVERSIONS, as the running kernel is |
| 6. Symbol table stripped | dmesg shows module has no symbols (stripped?) | Install the unstripped file, or strip with --strip-debug only |
| 7. Driver already built into the kernel | dmesg shows exports duplicate symbol | Do not load the second copy, or build the driver as a module only |
Cause 1: the version magic differs
Every module carries a vermagic string in its .modinfo section. check_modinfo() compares it with the kernel’s own string and, on a mismatch, returns -ENOEXEC and prints this line (the kernel’s format from the source, with example values):
mydriver: version magic '7.3.0 SMP preempt mod_unload aarch64' should be '7.3.0 SMP preempt_rt mod_unload aarch64'The string is assembled in include/linux/vermagic.h from the kernel release, then one word each for CONFIG_SMP, the preemption model (preempt or preempt_rt), CONFIG_MODULE_UNLOAD (mod_unload), CONFIG_MODVERSIONS (modversions), an architecture word, and a RANDSTRUCT_ seed hash when structure layout randomisation is enabled. same_magic() compares with strcmp(), so the strings must be identical, including any suffix after the version number. One exception: when the module carries symbol checksums, the release is skipped and only the remaining words are compared.
Print the module’s string and the running release; the kernel log line shows the full expected string:
root@imx8mp-evk:~# modinfo -F vermagic mydriver.ko
root@imx8mp-evk:~# uname -rThis is the most frequent reason for Invalid module format on a BSP. Rebuild the module against the build tree that produced the running kernel: the same source, .config and local version suffix. The word that differs between the two strings names the option to correct. If a string contains RANDSTRUCT_, only the build that generated that seed can produce a matching module.
Cause 2: the module_layout checksum differs
On a kernel built with CONFIG_MODVERSIONS, check_modstruct_version() runs before the version magic comparison. It looks up one exported symbol, module_layout, and compares its checksum with the one recorded in the module. On a mismatch check_version() in kernel/module/version.c prints:
mydriver: disagrees about version of symbol module_layoutmodule_layout() is an empty function whose prototype names struct module, struct modversion_info, struct kernel_param, struct kernel_symbol and struct tracepoint. Its checksum changes when any of those definitions changes, so the line appears when the build tree and the running kernel differ in source or configuration. Because this check runs first, such a module never reaches the version magic comparison.
The kernel prints the two checksum values only at debug level. With CONFIG_DYNAMIC_DEBUG and debugfs mounted, enable that line and load again:
root@imx8mp-evk:~# echo 'file kernel/module/version.c +p' > /sys/kernel/debug/dynamic_debug/control
root@imx8mp-evk:~# insmod mydriver.ko
root@imx8mp-evk:~# dmesg | tailRebuild against the tree and the Module.symvers file from the kernel build that produced the running image. If the line names any other symbol, the load fails later with a different error number and kmod prints Invalid parameters, not Invalid module format.
Cause 3: wrong architecture, compressed or damaged file
Before any version check, elf_validity_ehdr() confirms that the file is a relocatable ELF object for the kernel’s architecture. Its message formats are:
Invalid ELF header len %lu
Invalid ELF header magic: != %s
Invalid ELF header type: %u != %u
Invalid architecture in ELF header: %uThe number in the last line is the ELF machine value from include/uapi/linux/elf-em.h: 62 is x86-64, 40 is 32-bit ARM, 183 is AArch64 and 243 is RISC-V. A value of 62 on an ARM board means the module was compiled for an x86-64 build host, usually because ARCH and CROSS_COMPILE were not passed to make. A magic failure means the first four bytes are not an ELF header, which is what the kernel sees when a compressed .ko.gz, .ko.xz or .ko.zst file reaches it without being decompressed, or when a transfer was incomplete. Confirm on the build host, and compare the checksum with the copy on the board:
raghu@techveda.org:~$ readelf -h mydriver.ko
raghu@techveda.org:~$ sha256sum mydriver.koThe Type field must be REL and the Machine field must match the board. Rebuild with the cross toolchain, decompress the file, or copy it again.
Cause 4: the struct module size differs
Each module contains one instance of struct module in its .gnu.linkonce.this_module section, compiled from the headers of the build tree. In the 6.6 series and later, elf_validity_cache_index_mod() compares the size of that section with the kernel’s own sizeof(struct module) and prints:
module mydriver: .gnu.linkonce.this_module section size must match the kernel's built struct module size at run timestruct module in include/linux/module.h has many fields inside #ifdef blocks, among them CONFIG_TRACEPOINTS, CONFIG_KALLSYMS and CONFIG_MODULE_SIG. A build tree with a different setting for such an option can produce a different size. This test runs before both version checks, so on these kernels it can be the only line printed for a configuration mismatch. Compare the two configurations, where running.config is the decompressed /proc/config.gz from the board:
raghu@techveda.org:~$ linux/scripts/diffconfig running.config linux/.configThe fix is the same as for cause 1.
Cause 5: the module carries no symbol versions
This cause returns Invalid module format and prints nothing in the kernel log. When the kernel exports checksums and the module has no __versions section, check_version() calls try_to_force_load(). Unless the kernel was built with CONFIG_MODULE_FORCE_LOAD, which is default n, that function returns -ENOEXEC without a message. A module with no vermagic field takes the same silent path. Confirm with:
raghu@techveda.org:~$ readelf -S mydriver.ko | grep versionroot@imx8mp-evk:~# zcat /proc/config.gz | grep MODVERSIONSIf the board reports CONFIG_MODVERSIONS=y and the module shows neither __versions nor __version_ext_crcs, the build tree was configured without module versioning. Rebuild against a tree with the running kernel’s configuration.
Warning: the same function is why insmod --force and modprobe --force still fail on a kernel without CONFIG_MODULE_FORCE_LOAD. Where forced loading is enabled, it bypasses the checks that protect kernel memory from a module with a different structure layout, and it taints the kernel. A forced module can crash the system or corrupt data. Do not use it on a product or on a board holding data you need.
Cause 6: the symbol table was stripped
The loader resolves the module’s imports through its ELF symbol table. If the file has no symbol table section, the kernel prints:
mydriver: module has no symbols (stripped?)The usual source is an image build or packaging script that strips more than debug information. Kbuild’s own install step, enabled with INSTALL_MOD_STRIP=1, uses --strip-debug. Confirm on the build host:
raghu@techveda.org:~$ readelf -S mydriver.ko | grep SYMTABNo output means the table is gone. Install the unstripped file, or strip it with --strip-debug only.
Cause 7: the driver is already built into the kernel
After the earlier checks pass, verify_exported_symbols() rejects a module that exports a symbol the kernel or another loaded module already exports. The format string in the source is:
%s: exports duplicate symbol %s (owned by %s)The owner is kernel when the first copy is built in, as happens when a BSP kernel has the driver set to y and an out-of-tree copy is loaded as well. Confirm with:
root@imx8mp-evk:~# grep mydriver /lib/modules/$(uname -r)/modules.builtinUse the built-in driver, or change the kernel option to m or n. Where such a driver should live is discussed in In-Tree vs Out-of-Tree Driver: Where Your Code Should Live.
If none of these
If Invalid module format is still unexplained, note that the loader has further -ENOEXEC exits for malformed section headers, for objects with common symbols (please compile with -fno-common) and for livepatch modules on a kernel without livepatch support. Each prints its own line. If dmesg is empty and cause 5 is excluded, write file kernel/module/main.c +p to the dynamic debug control file and repeat the load. Then capture the full dmesg output, modinfo mydriver.ko, readelf -h -S mydriver.ko, uname -a and the kernel configuration. For a vendor kernel, send these to the BSP supplier. For a mainline or stable kernel, MAINTAINERS lists linux-modules@vger.kernel.org for module support.
Versions
The version magic, disagrees about version of symbol and module has no symbols (stripped?) lines are worded identically in 5.10.274, 5.15.225, 6.1.192, 6.6.162, 6.12.117, 6.18.63, 7.3 and 7.4-rc2. The differences are these:
- In 5.10 and 5.15 the loader is one file,
kernel/module.c; use that name with dynamic debug. From 6.1 it iskernel/module/main.candkernel/module/version.c. - In 5.10.274 the ELF header tests of cause 3 return
-ENOEXECwithout printing. TheInvalid ELF headerlines are present from 5.15.225. - The
struct modulesize test of cause 4 is absent in 6.1.192 and present from 6.6.162. - The randomisation word is
RANDSTRUCT_PLUGIN_in 5.10 and 5.15, andRANDSTRUCT_from 6.1. - The extended version sections
__version_ext_crcsand__version_ext_namesare handled in 6.18.63 and not in 6.12.117.
What was checked and what could not be verified
Every message, function name and option above was read from kernel source at the tags listed above, from kmod’s master branch (its NEWS file is headed kmod 34) and from the BusyBox master branch on its GitHub mirror. Nothing in this guide was run on hardware. The example lines are the kernel’s format strings with illustrative values, not captured output. The ranking of causes is a judgement, not a measurement. Two points remain unverified. The kernel build documentation states that make modules_prepare does not produce Module.symvers; which of these checks, if any, rejects a module built from such a tree was not established. Which stripping options remove a module’s symbol table was not tested.
Key takeaways
Invalid module formatis kmod’s wording forENOEXEC; the reason is in the kernel log.- An empty kernel log after
Invalid module formatpoints to a module without symbol versions, or to a 5.10-series kernel rejecting the ELF header. - Most causes share one remedy: build the module from the source, configuration and
Module.symversof the running kernel.
Frequently asked questions
Does Invalid module format mean the kernel version is wrong?
Not necessarily. The message reports only the error number ENOEXEC. A different configuration with the same release, a module compiled for the wrong architecture, a stripped symbol table and a driver that is already built in all produce Invalid module format.
Why does dmesg show nothing after the failed insmod?
A module with no symbol versions, loaded on a kernel built with CONFIG_MODVERSIONS and without CONFIG_MODULE_FORCE_LOAD, is rejected without a message. In the 5.10 series the ELF header tests are also silent.
Will insmod –force load the module anyway?
Only on a kernel built with CONFIG_MODULE_FORCE_LOAD, which is off by default. Without that option the forced path returns ENOEXEC again. Where it is enabled, forcing bypasses the checks that protect kernel memory and taints the kernel.
References
- Linux v7.3, kernel/module/main.c — load_module(), early_mod_check(), check_modinfo(), elf_validity_ehdr(), elf_validity_cache_index_mod(), verify_exported_symbols(), try_to_force_load()
- Linux v7.3, kernel/module/version.c — check_version(), check_modstruct_version(), same_magic(), module_layout()
- Linux v7.3, include/linux/vermagic.h — composition of the version magic string
- Linux v7.3, kernel/module/Kconfig — MODULE_FORCE_LOAD, MODVERSIONS
- Linux v5.10.274, kernel/module.c — the single-file loader in the 5.10 and 5.15 series; longterm tags 5.15.225, 6.1.192, 6.6.162, 6.12.117 and 6.18.63 were read from the same stable tree
- Building External Modules — modules_prepare and Module.symvers
- Kbuild — INSTALL_MOD_STRIP
- kmod, tools/insmod.c and tools/modprobe.c — mod_strerror() and the modprobe error path
- BusyBox, modutils/modutils.c — moderror()




