HomeAbout UsContact Us

Fixing Zephyr Build Errors from Missing Device Tree Overlays

By Jithin Tom
September 08, 2026
3 min read
Fixing Zephyr Build Errors from Missing Device Tree Overlays

Table Of Contents

01
Problem Statement: The Missing Overlay Build Error
02
Root Cause Analysis: How Zephyr Collects and Validates Overlays
03
Systematic Resolution Workflow
04
Complete Working Example: STM32F4 Discovery Pin Remap
05
Unified Devicetree Generation Architecture
06
Key Takeaways
07
Related Reading
08
References
09
Frequently Asked Questions

Zephyr build failures due to missing device tree overlays are a common hurdle for firmware developers configuring board variants, peripheral shields, or application-specific pinouts. The error typically surfaces during the CMake configuration phase invoked by west build, terminating with a fatal “File not found” or “No such file or directory” error before compilation even begins.

This guide provides an exhaustive, root-cause investigation into how Zephyr’s build system processes overlays, explains why missing overlay errors occur in CMake, and demonstrates deterministic fixes to ensure reliable builds.

Problem Statement: The Missing Overlay Build Error

When initiating a build with west build, the CMake configuration phase halts abruptly. The console output typically presents one of two error patterns:

Pattern 1: CMake Devicetree Validation Failure

-- Found BOARD.dts: /zephyrproject/zephyr/boards/arm/stm32f4_discovery/stm32f4_discovery.dts
CMake Error at /zephyrproject/zephyr/cmake/modules/dts.cmake:189 (message):
File not found: /workspace/app/boards/stm32f4_disco.overlay
Call Stack (most recent call first):
/zephyrproject/zephyr/cmake/modules/zephyr_default.cmake:132 (include)
/zephyrproject/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:66 (include)
CMakeLists.txt:4 (find_package)

Pattern 2: Device Tree Compiler (DTC) Invocation Failure

Error: /workspace/app/custom.overlay: No such file or directory
FATAL ERROR: Unable to parse input tree
CMake Error at /zephyrproject/zephyr/cmake/modules/dts.cmake:265 (message):
command failed with return code: 1

These diagnostics indicate that Zephyr’s build pipeline was explicitly instructed—or implicitly configured via cache—to consume an overlay file that does not exist at the target filesystem path.

Root Cause Analysis: How Zephyr Collects and Validates Overlays

To resolve overlay build failures, it is critical to understand how Zephyr’s CMake scripts process devicetree inputs. A central tenet of Zephyr architecture is that application developers must never edit board .dts files directly, nor should they add #include "some.overlay" directives inside board DTS files. Overlays are managed entirely at the build system level.

1. The Overlay Resolution Pipeline in dts.cmake

During the configuration step, /zephyr/cmake/modules/dts.cmake builds the unified devicetree using the following sequence:

  1. Board DTS Selection: Identifies the base board devicetree <board>.dts.
  2. Automatic Overlay Discovery:
    • Searches the application directory for app.overlay.
    • Searches the application’s boards/ directory for <board>.overlay or <board>_<revision>.overlay.
  3. Shield Overlays:
    • If --shield <shield_name> is supplied, CMake resolves <shield_name>.overlay from standard shield directories.
  4. Explicit Overlays:
    • Reads user-specified overlays from CMake variables DTC_OVERLAY_FILE and EXTRA_DTC_OVERLAY_FILE.
  5. Path Validation:
    • Iterates through the aggregated list of overlay files. For each entry, CMake verifies existence using if(NOT EXISTS ${file}). If any file is absent, CMake terminates with a fatal File not found error.
  6. Preprocessing and Generation:
    • Feeds the base .dts concatenated with all verified .overlay files into the C Preprocessor (gcc -E -P -x assembler-with-cpp).
    • Compiles the preprocessed output with dtc into build/zephyr/zephyr.dts.
    • Executes Python scripts (scripts/dts/gen_defines.py) to generate C preprocessor macros in build/zephyr/include/generated/devicetree_generated.h.

2. Primary Failure Mechanisms

  • Stale CMakeCache.txt: When an overlay is discovered or passed on the command line, CMake stores the file path in CMakeCache.txt under DTC_OVERLAY_FILE. If you rename or delete that file (for example, switching from custom.overlay to app.overlay), subsequent incremental west build runs still inspect the cached path and immediately abort.
  • Path Resolution Semantics: Paths passed to -DEXTRA_DTC_OVERLAY_FILE are resolved relative to the current working directory of the shell or CMake invocation, not necessarily the application source tree unless an absolute path or ${APPLICATION_SOURCE_DIR} is used.
  • Shield Name Mismatches: Specifying --shield my_sensor_shield when the actual shield definition file is boards/shields/my_sensor/my_sensor.overlay will trigger a missing overlay failure.
  • Filesystem Case Sensitivity: Host build environments running on Linux (or Windows WSL) enforce strict case sensitivity. A mismatch between STM32F4_Discovery.overlay and stm32f4_discovery.overlay causes immediate file lookup failure.

Systematic Resolution Workflow

Step 1: Inspect the CMake Log for the Missing Path

Check the exact file path reported in the error message. Note whether the path is absolute or relative, and confirm whether it points to:

  • An application-level file (app.overlay)
  • A board-specific override (boards/<board>.overlay)
  • An explicitly supplied flag (EXTRA_DTC_OVERLAY_FILE)

Step 2: Flush the Stale Build Cache (Pristine Build)

If the overlay was deleted, renamed, or relocated, the cached variable in build/CMakeCache.txt must be purged. Execute a pristine build using the -p always flag:

west build -p always -b stm32f4_discovery

This clears the entire build directory, forcing CMake to scan the directory tree afresh.

Step 3: Verify Relative and Absolute Paths

When specifying overlays manually via the command line, separate multiple overlay paths with semicolons (the standard CMake list separator) and use valid filesystem paths:

# Using relative path from application directory
west build -b stm32f4_discovery -- -DEXTRA_DTC_OVERLAY_FILE="dts/sensors.overlay"
# Using absolute path
west build -b stm32f4_discovery -- -DEXTRA_DTC_OVERLAY_FILE="$PWD/dts/sensors.overlay"

In CMakeLists.txt, always anchor paths to ${APPLICATION_SOURCE_DIR}:

# Recommended CMakeLists.txt overlay inclusion
list(APPEND EXTRA_DTC_OVERLAY_FILE "${APPLICATION_SOURCE_DIR}/custom.overlay")

Step 4: Adhere to Automatic Discovery Naming Conventions

To minimize configuration overhead, leverage Zephyr’s automatic overlay discovery. Structure your application directory as follows:

my_zephyr_app/
├── CMakeLists.txt
├── prj.conf
├── app.overlay <-- Automatically applied to ALL boards
├── boards/
│ ├── stm32f4_discovery.overlay <-- Applied ONLY when -b stm32f4_discovery
│ └── nucleo_f401re.overlay <-- Applied ONLY when -b nucleo_f401re
└── src/
└── main.c

When files are placed in these standard locations, omit -DEXTRA_DTC_OVERLAY_FILE. CMake will automatically locate and merge them.

Complete Working Example: STM32F4 Discovery Pin Remap

Here is a complete walkthrough resolving a missing overlay error and successfully modifying hardware definitions.

1. Build Failure Diagnostic

The developer attempts to compile an application with an external SPI sensor overlay:

$ west build -b stm32f4_discovery -- -DEXTRA_DTC_OVERLAY_FILE="overlay/spi_sensor.overlay"

Output:

CMake Error at /zephyrproject/zephyr/cmake/modules/dts.cmake:191 (message):
File not found: overlay/spi_sensor.overlay

Checking the directory reveals the folder was named overlays/ (plural), not overlay/:

$ ls overlays/
spi_sensor.overlay

2. Apply Automatic Discovery

Rather than passing lengthy command-line arguments, move the overlay into boards/:

$ mkdir -p boards
$ cp overlays/spi_sensor.overlay boards/stm32f4_discovery.overlay

The content of boards/stm32f4_discovery.overlay:

/* Enable SPI1 and attach an external sensor */
&spi1 {
status = "okay";
pinctrl-0 = <&spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pa7>;
pinctrl-names = "default";
cs-gpios = <&gpioc 4 GPIO_ACTIVE_LOW>;
sensor: sensor@0 {
compatible = "bosch,bme280";
reg = <0>;
spi-max-frequency = <10000000>;
};
};

3. Pristine Rebuild and Verification

Rebuild with cache flush:

$ west build -p always -b stm32f4_discovery

Console confirms overlay inclusion:

-- Found BOARD.dts: .../stm32f4_discovery/stm32f4_discovery.dts
-- Found devicetree overlay: .../my_zephyr_app/boards/stm32f4_discovery.overlay
-- Generating zephyr.dts
-- Generated zephyr.dts: .../my_zephyr_app/build/zephyr/zephyr.dts
[100%] Built target zephyr_final

Verify that the final device tree incorporates the changes:

$ grep -A 10 "sensor@0" build/zephyr/zephyr.dts

Unified Devicetree Generation Architecture

+-------------------------+ +-------------------------+ +-------------------------+
| Base Board DTS | | Automatic Overlays | | Command-Line / CMake |
| (stm32f4_discovery.dts) | | (app.overlay, | | EXTRA_DTC_OVERLAY_ |
| | | boards/<board>.overlay) | | FILE / Shields |
+------------+------------+ +------------+------------+ +------------+------------+
| | |
+-------------------------------+-------------------------------+
|
v
+-----------------------------------------------------------------------------------------+
| zephyr/cmake/modules/dts.cmake |
| |
| 1. Validate all overlay paths via if(NOT EXISTS <file>) |
| 2. If missing -> emit fatal CMake Error "File not found" |
| 3. If valid -> compile aggregated devicetree source list |
+--------------------------------------------+--------------------------------------------+
|
v
+-----------------------------------------------------------------------------------------+
| C Preprocessor (gcc -E -P) |
| Includes DTS headers, macros, and pre-processes hardware nodes |
+--------------------------------------------+--------------------------------------------+
|
v
+-----------------------------------------------------------------------------------------+
| dtc (Device Tree Compiler) |
| Checks syntax, resolves node labels, & outputs pre-compiled DTS |
+--------------------------------------------+--------------------------------------------+
|
v
+----------------------+----------------------+
| |
v v
+-------------------------------+ +-------------------------------+
| Final Device Tree | | Generated C Macro Header |
| build/zephyr/zephyr.dts | | build/zephyr/include/ |
| | | generated/ |
| | | devicetree_generated.h |
+-------------------------------+ +-------------------------------+

Key Takeaways

  • Never use #include for .overlay files: Overlays are dynamic CMake inputs. Incorporating .overlay files directly into .dts sources violates Zephyr component modularity.
  • Flush the build cache: If you rename or delete an overlay file, run west build -p always to eliminate stale paths in CMakeCache.txt.
  • Prefer automatic discovery: Use app.overlay for cross-board changes and boards/<board>.overlay for board-specific pinouts.
  • Inspect build/zephyr/zephyr.dts: Always verify that your overlay nodes and property modifications correctly merged into the final generated devicetree.

References

  1. Zephyr Project Documentation, “Devicetree Overlays”, https://docs.zephyrproject.org/latest/build/dts/howtos.html
  2. Zephyr Project Documentation, “Zephyr Build System”, https://docs.zephyrproject.org/latest/build/
  3. Zephyr Project Documentation, “West (Zephyr’s Meta-Tool)“, https://docs.zephyrproject.org/latest/develop/west/index.html
  4. Devicetree Specification Release v0.4, Devicetree.org, https://www.devicetree.org/specifications/
  5. STMicroelectronics, “STM32F4 Discovery Kit (STM32F407VG)“, https://web.archive.org/web/20241113131657/https://www.st.com/en/evaluation-tools/stm32f4discovery.html

Frequently Asked Questions

What causes Zephyr build failures due to missing device tree overlays?

Zephyr builds fail with a missing overlay error when CMake's `dts.cmake` module encounters an overlay path in `DTC_OVERLAY_FILE` or `EXTRA_DTC_OVERLAY_FILE` that does not exist on disk, when a specified shield overlay is missing, or when an auto-discovered overlay was deleted while remaining cached in `CMakeCache.txt`.

How do you identify which overlay is missing in a Zephyr build error?

Examine the CMake configuration log for `CMake Error at .../cmake/modules/dts.cmake: File not found:` followed by the unresolved file path. If `dtc` fails instead, check for compiler preprocessor errors indicating missing header or include paths.

What is the correct way to add a missing device tree overlay in Zephyr?

Place the `.overlay` file in the application root (e.g., `app.overlay`) or under `boards/<board_name>.overlay` for automatic discovery. If passing custom overlays via `-DEXTRA_DTC_OVERLAY_FILE`, verify relative paths against the application directory. Perform a pristine build (`west build -p always`) to flush stale cached overlay paths.

Tags

zephyrdevice-treebuildoverlaysstm32

Share


Previous Article
Fixing FreeRTOS Event Group Timer Queue Overflow in ISR Context
Jithin Tom

Jithin Tom

A Closer Look at C/C++, RTOS, and Embedded Systems

Related Posts

Linker Garbage Collection for Faster STM32 Builds
Linker Garbage Collection for Faster STM32 Builds
September 16, 2026
5 min
© 2026, All Rights Reserved.
Powered By Netlyft

Quick Links

Advertise with usAbout UsContact Us

Social Media