Source: https://mokxi.com/learn/arduino-control-reaches-end-of-non-void-function
Updated: 2026-10-26

Learn

# Fixing "control reaches end of non-void function" in Arduino

Beginner

Written by the Mokxi team, updated October 26, 2026

Start building free Open the editor

Or see every lesson.

- 505 parts on the bench
- 45 boards running now
- 1.00x real time, on every board

Hold the button

Hold the button and the LED lights. The guide below moves the button test into a bool function and leaves out one return, and the sketch then says pressed when nobody is pressing.

control reaches end of non-void function means a function that promises to give back a value can get to its closing } without a return. The type in front of its name, int, bool, float or String, is that promise; only void means "gives back nothing". Usually the function returns inside an if and has no return for when the if is false, or a switch has no default. The fix is a return with a value on every path, most simply as the last line.

On an Uno in the Arduino IDE it is only a warning, and the IDE hides warnings unless you turn them on, so the sketch builds and the function gives back whatever was left over. On the ESP32 the core makes it an error, [-Werror=return-type]. Mokxi compiles with clang, which warns non-void function does not return a value in all control paths. The circuit above is the button and LED; below, its button test misses a return and says "pressed" when nobody touches it.

## A return inside an if, and nothing after it

Here is the button sketch’s test as a function. It returns true when the pin reads LOW, and says nothing for the other case. Clang built it with one warning, non-void function does not return a value in all control paths, at the closing brace on line 7, and Mokxi’s build tab says: "The type in front of this function's name says it gives back a value, but it can reach its end without a return. Add return and the value as its last line (return v;), or make it void if it gives back nothing. Without one the value is whatever happens to be left over."

We ran it on the engine for two seconds without touching the button, and it printed "pressed" five times out of five. Held down, it printed "pressed" five times too, so the sketch cannot tell the two apart. With return false; added as the last line, it printed "not pressed" five times when left alone, and "pressed" five times while the button was held.

GCC 13 says control reaches end of non-void function [-Wreturn-type] for the same function, as a warning, unless the core turns it into an error.

Broken: no return when the button is up

Open this sketch in the editor The code alone: the editor places the board and the parts it can read from the sketch.

## What the function gives back without a return

The C++ standard says that flowing off the end of a function that returns a value is undefined behavior: the program is wrong, and nothing at all is promised about what happens next. In practice the caller reads whatever was left in the place the value should have been, and the compiler is allowed to assume that path never happens and build something stranger still.

You can see that it is not a value you would guess. int doubled(int x) that works out int y = x * 2; and forgets return y; printed 16 for doubled(21), and 16 again for doubled(5). With the return it printed 42. A function level(raw) that returns 2 above 600 and 1 above 300, and nothing below, printed 1 for level(100), the same as for 400. Those numbers are what this build did on the engine, not something to rely on: another compiler, another board or one more line of code can change them.

## "no return statement in function returning non-void"

When the function has no return at all, GCC 13 words the warning differently: no return statement in function returning non-void [-Wreturn-type]. Clang says non-void function does not return a value, without "in all control paths". It is the same mistake, and both search terms lead here.

Sometimes the function never meant to give anything back, and its type is the mistake: a helper that blinks an LED does not need to be int. Change it to void, and leave out the return.

## A switch without a default

A function that returns from each case of a switch still reaches its end when the value matches none of them. const char *name(int mode) with a case for 0 and a case for 1 gave clang’s non-void function does not return a value in all control paths and GCC’s control reaches end of non-void function, even if the sketch only ever passes 0 or 1. Add default: return "unknown"; inside the switch, or a return after it.

## Why the ESP32 stops with -Werror=return-type

The Arduino IDE passes the warning flags you pick in its preferences. For the Uno, the AVR core’s default is -w, no warnings at all, so the IDE shows nothing. The ESP32 core adds -Werror=return-type to every build, which turns this one warning into an error: GCC 13 with that flag stopped with control reaches end of non-void function [-Werror=return-type]. That is why a sketch that built on an Uno for years fails when it moves to an ESP32.

The answer is the same fix, not a different flag. Mokxi gives the warning on the Uno and on the ESP32 alike, and still builds, so you see the problem without the build stopping. Turning warnings on in the IDE, File, Preferences, Compiler warnings, shows it on the Uno too.

The button test with a return on every path

Open this sketch in the editor The code alone: the editor places the board and the parts it can read from the sketch.

Open this circuit in the editor. Arduino Uno: a button and an LED, wired as it runs at the top of this page. Change a part or a value and run it again.
Open the circuit

## Questions

What does "control reaches end of non-void function" mean?

A function with a return type other than void can reach its closing } without a return statement. Add a return with a value on every path, or make the function void.

Is it an error or a warning?

In GCC and clang it is a warning, and the Uno builds. The ESP32 core builds with -Werror=return-type, which makes it an error there.

What value does the function return without a return statement?

None that you can count on. The standard calls it undefined behavior. On the engine a broken doubled(21) printed 16, and a button test said pressed when it was not.

How do I fix -Werror=return-type on the ESP32?

Find the function the error names and add the missing return, usually as its last line, or a default case in its switch. Do not change the core’s flags.

Related

## Keep going

Arduino Compile Errors Explained, With the Fixes Arduino Functions: Write It Once, Call It Anywhere Arduino if else: One Branch Runs, and Why Arduino Button Debounce: See the Bounce, Then Fix It Arduino Data Types: int, long, float and byte Arduino "expected ';' before" and Similar Errors The pushbutton part The ESP32 DevKit board The online Arduino compiler The project page, with the full sketch Beginner

Sources

## Where the facts on this page come from

- cppreference: the return statement, and flowing off the end of a function
- arduino-esp32: platform.txt, compiler.common_werror_flags=-Werror=return-type
- ArduinoCore-avr: platform.txt, compiler.warning_flags=-w

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building free Open the editor
