Learn

Fixing "expected unqualified-id" in Arduino

Beginner

Or see every lesson.

  • 455parts on the bench
  • 43boards running now
  • 1.00xreal time, on every board
Arduino Uno: blink, ready to breaklive0.000 s 0.00x
Click to open it in the editor
The LED on pin 13 blinks once a second. Change void loop() { to void loop(); { and press Run: the build stops with expected unqualified-id.

expected unqualified-id means the compiler was waiting for a name, the name of a variable or a function it was about to declare, and found something else: a keyword such as if, a number, a string or a brace. Most of the time the line is outside every function, where only declarations are allowed, because a } above it closed setup() or loop() too early. The other causes are a #define that turned a name into a number, a semicolon after void loop(), and a name that is not a legal name.

The word after "before" in the Arduino IDE’s message tells you which: before 'if' and before 'else' are code outside a function, before numeric constant and before string constant are usually a #define, and before '{' token is a function’s first line ended with a semicolon. Mokxi compiles with clang, which says expected unqualified-id and nothing more, so the guide below gives both wordings for each cause. The circuit above is the Uno blink. Open it, add a semicolon after void loop() and press Run to see the error.

"before 'if'", "before 'else'" and "before 'for'": code outside a function

Between functions, C++ allows declarations and nothing else. An if, a for or a call such as digitalWrite(13, HIGH); has to be inside setup(), loop() or a function of your own. When a stray } ends a function halfway down, everything after it is suddenly outside, and the first line that does something gets this error.

Here is the button sketch with one } too many after its first line in loop(). Clang stopped with four errors: expected unqualified-id at the if on line 11 and at the else on line 13, a type specifier is required for all declarations at the delay(5); on line 16, and extraneous closing brace ('}') on line 17. GCC says expected unqualified-id before 'if', expected unqualified-id before 'else', expected constructor, destructor, or type conversion before '(' token and expected declaration before '}' token for the same four lines. Mokxi’s build tab explains the first: "This line is outside every function, where only declarations may go. Often a } above it closed a function too early, or a statement belongs inside setup() or loop()."

The fix is to delete the extra brace, and the place to look is just above the first error. Auto Format, Ctrl+T (Cmd+T on a Mac) in the Arduino IDE and in Mokxi’s code editor, makes it easy to see: the lines after the early brace jump out to the left margin.

Broken: a } that closes loop() after its first line
const int BUTTON_PIN = 2;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  bool pressed = digitalRead(BUTTON_PIN) == LOW;
  }
  if (pressed) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
  delay(5);
}

A loop or an else that was never inside a function

The same message comes from code written outside a function on purpose, often by someone used to Python, where a file runs from the top. A for loop above void loop() that prints 0, 1 and 2 gave clang’s one expected unqualified-id at the for, while GCC said expected unqualified-id before 'for' and then 'i' does not name a type twice. Move the loop into setup() to run it once.

An else after the closing brace of loop() fails the same way, expected unqualified-id before 'else' in GCC’s words. The if it belongs to is inside the function, so the else has to be too: its } and the function’s } are in the wrong order.

"before numeric constant": a #define and a variable with one name

#define LED 13 tells the preprocessor to replace the word LED with 13 everywhere after it, before the compiler sees the code. If the sketch then declares int LED = 13;, the compiler reads int 13 = 13;, and 13 cannot be a name. GCC says expected unqualified-id before numeric constant. Clang says expected unqualified-id, with a note that points at the #define: expanded from macro 'LED'. The same happens to const int LED = 13; under the #define.

Keep one of the two. A const int is the better choice, because it has a type and follows the normal rules for names. The same clash happens with a library: if a header you include defines a word as a number, a variable of yours with that name stops the build here.

A name that starts with a digit gives the GCC message too. int 2ndLed = 12; is read as the number 2 followed by a word, so GCC says expected unqualified-id before numeric constant, and clang says expected unqualified-id and then invalid suffix 'ndLed' on integer constant where the name is used. Names are letters, digits and underscores, and the first one cannot be a digit: led2 or secondLed both work.

One name for the pin, declared once
const int LED = 13;

void setup() {
  pinMode(LED, OUTPUT);
}

void loop() {
  digitalWrite(LED, HIGH);
  delay(500);
  digitalWrite(LED, LOW);
  delay(500);
}

"before string constant"

The text version of the same clash. With #define NAME "Mokxi" above String NAME = "Mokxi";, the second line becomes String "Mokxi" = "Mokxi";. GCC says expected unqualified-id before string constant; clang says expected unqualified-id, with expanded from macro 'NAME' in the note. Rename one, or drop the #define and keep the String.

"before '{' token": a semicolon after void loop()

void loop(); with a semicolon is a declaration: it says a function called loop exists somewhere, and ends there. The { on the next line then opens a block that belongs to nothing. GCC says expected unqualified-id before '{' token; clang says expected unqualified-id and points at the brace. This is the break the demo above suggests: void loop(); { on the blink sketch gave clang’s message at the brace.

Delete the semicolon. A function’s first line runs straight into its opening brace, void loop() {, and only lines inside it end with a semicolon.

A keyword used as a name

C++ keeps some words for itself, among them new, delete, class, this, switch, case and default. int new = 5; gave expected unqualified-id from clang and expected unqualified-id before 'new' from GCC. Pick another name, such as newValue. A word Arduino defines as a number, such as HIGH, LOW, OUTPUT or A0, fails the "numeric constant" way above for the same reason as LED.

Questions

What does "expected unqualified-id" mean in Arduino?

The compiler expected a name for something it was about to declare and found a keyword, a number, a string or a brace instead. Usually the line is outside every function because a } closed one too early.

What does "expected unqualified-id before numeric constant" mean?

A name became a number before the compiler saw it, nearly always because a #define gives that word a value, as in #define LED 13 followed by int LED = 13;. Keep the const int and delete the #define, or rename one.

Why does it say "expected unqualified-id before 'if'"?

The if is outside every function. A } above it ended setup() or loop() early. Delete that brace, or move the if into the function it belongs to.

Does Mokxi show the same error?

Mokxi compiles with clang, which says expected unqualified-id without the "before" part, and adds a note pointing at the #define when one is the cause. The fixes are the same.

Build this for real

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