Lesson 5 of 6
C++ error messages have a reputation for being terrifying. Some of them earn it. But the ones you'll hit as a beginner follow a handful of patterns, and once you can recognise them you'll fix most in seconds.
The skill isn't memorising messages. It's knowing where to look and what to ignore.
The anatomy of an error
Every g++ error has the same shape:
hello.cpp:5:29: error: expected ';' before '}' token
5 | std::cout << "Hello\n"
| ^
| ;
6 | }
| ~
Reading it:
hello.cpp— the file.:5:29— line 5, column 29. Your editor shows both.error:— severity.error:stops the build;warning:doesn't;note:is extra context attached to the message above it.- the message — what went wrong.
- the excerpt — your actual line, with
^pointing at the column and, here, a suggested fix.
Rule one: fix the first error
This is the most important habit in the lesson.
When the compiler gets confused, it keeps trying, and every subsequent line looks wrong to it. One missing semicolon can produce twenty errors. Nineteen of them are noise.
Always scroll up to the first error, fix that one thing, and recompile. Very often the rest vanish. Fixing the errors bottom-up — or worse, all at once — is how beginners spend an hour on a five-second problem.
The errors you'll actually hit
Missing semicolon
// WILL NOT COMPILE
#include <iostream>
int main() {
std::cout << "Hello\n"
return 0;
}
error: expected ';' before 'return'
The compiler reports the error at return, not at the end of the previous line — it only knows
something's wrong once it reaches a token that can't continue the statement. The fix is usually
on the line above the one named.
Undeclared identifier
// WILL NOT COMPILE
#include <iostream>
int main() {
std::cout << mesage << "\n";
return 0;
}
error: 'mesage' was not declared in this scope
"I've never heard of this name." Causes, in order of likelihood: a typo, a variable used before it's declared, or a variable declared inside a different block (lesson 4.6).
Missing std::
// WILL NOT COMPILE
#include <iostream>
int main() {
cout << "Hello\n";
return 0;
}
error: 'cout' was not declared in this scopenote: suggested alternative: 'std::cout'
Same error, different cause — the name exists, but in the std namespace. Note that g++ suggests
the fix. Read the note: lines; they're often the answer.
Missing include
// WILL NOT COMPILE
int main() {
std::cout << "Hello\n";
return 0;
}
error: 'cout' is not a member of 'std'
Subtly different again: the compiler knows std exists but can't find cout in it, because
nothing declared it. You forgot #include <iostream>.
Type mismatch
// WILL NOT COMPILE
#include <string>
int main() {
int count = "seven";
return 0;
}
error: invalid conversion from 'const char*' to 'int'
You gave it a value of the wrong type. These messages name both types — the one you supplied and the one required — which usually tells you exactly what to fix.
When the message is genuinely huge
Templates (Module 12) and the STL can produce errors hundreds of lines long. The strategy is the same, just applied harder:
- Read the first line and the last line. The first says what failed; the last usually names the line in your code that started it.
- Look for your own filenames. Skip anything mentioning only
/usr/include/...— that's the library's internals, not your bug. - Find the
required from herenote. That's the bridge from library internals back to your code.
You'll get much more practice at this in lesson 12.8.
A note on tools
VS Code with the C/C++ extension (lesson 1.5) underlines most of these errors as you type, before you ever compile. That's a real speedup — but learn to read the compiler's own output anyway. It's what you'll get from a build server, a CI log, or a machine that isn't yours.
Try it
Deliberately break your hello.cpp in three different ways, one at a time: remove a semicolon,
misspell std::cout, and delete the #include. Compile each time and read the message before
fixing it.
Checkpoint
- Error format is
file:line:column: severity: message, with an excerpt and a^marker. - Always fix the first error, then recompile. Later errors are usually fallout.
- A missing semicolon is reported on the following line.
not declared in this scope= typo, or used before declaration, or missingstd::.is not a member of 'std'= usually a missing#include.- Read
note:lines — g++ frequently suggests the exact fix. - For huge template errors, read the first and last lines and look for your own filenames.
Questions about this lesson
Log in to ask a question.