Skip to content
Ameen Abozaid
PublishedBEG-008-L05

Reading compiler errors

  • Lesson 5 of 6
  • 12 min read
  • Beginner
On This Lesson 11 topics

Lesson Overview

You now know the parts of a program, so you can begin to understand what the compiler says when a part is wrong. This lesson teaches a routine for reading a javac error message: find the file and line, read the description, look at the caret, think about the likely cause, fix one thing, and recompile.

The recipe-card picture helps again. Imagine an assistant who reads your card before you start cooking and says "step 3 has no full stop" or "you wrote Sugr, I do not know that ingredient." The assistant is not scolding you. It is pointing at the exact spot.

Why this matters: reading compiler and tool output is a daily skill at every level of software work. Beginners often skim past error messages and guess. The fix is faster when you read.

This lesson builds on Lessons 1 to 4. The five mistakes we study are all ones you have met in passing: a missing semicolon, a misspelled name, a missing or extra brace, a wrong main line, and an unclosed string.

Learning Objectives

By the end of this lesson you will be able to:

  • Identify the file name, line number, description, source line, and caret in a javac message.
  • Explain why you read the first error first and recompile after each fix.
  • Explain why the real mistake can be on the line before the one reported.
  • Match the five common beginner messages to their likely causes.
  • Tell a compile-time error from a launch error such as a missing main.
  • Apply the fix loop: read, fix one thing, recompile.

Written Explanation

Anatomy of a message

Here is a real message, produced by JDK 21 for a program whose println statement lacks its semicolon:

text
Two.java:3: error: ';' expected
        System.out.println("A")
                               ^
1 error

It has five parts:

  1. The file and line: Two.java:3, so look at line 3 of Two.java.
  2. The description: error: ';' expected, a short sentence on what the compiler needed.
  3. The source line: a copy of the line, so you do not need to count.
  4. The caret ^: points to where the compiler noticed the problem.
  5. The count: 1 error, how many problems it reported in this run.

The exact words, spacing, and even the line number can differ between JDK versions, so use the messages in this lesson as typical, not word-for-word promises. What does not change is the habit of reading the five parts.

The fix loop

  1. Read the first error. Later errors can be side effects of the first, as one wrong bracket can confuse everything after it.
  2. Go to the line it names, and look at the line above too. A missing semicolon is noticed only when the next token arrives.
  3. Fix one thing.
  4. Recompile. Repeat until javac is silent.

A silent javac is success. It also means that a program can compile and still be wrong, and some errors only appear when you run it.

Why only fix one thing at a time? The compiler works in stages. If it finds a grammar problem such as a missing semicolon, it often reports only that and stops before checking names and types. After you fix it, a new error, hidden before, can appear. This is normal, not a sign that you made things worse. Here is an example with two mistakes:

java
public class F5 {
    public static void main(String[] args) {
        System.out.println("Hi")
        System.out.printn("B");
    }
}

The first compile reports only ';' expected at line 3. Fix it, compile again, and the compiler reports cannot find symbol for printn on line 4. Two mistakes, two rounds.

The five common messages

These are the ones you will meet in the first weeks. The messages below were produced by JDK 21.

MistakeTypical messageWhat it means
Missing semicolonerror: ';' expectedA statement was not finished. Look at the end of the reported line, and the line above.
Misspelled name or wrong caseerror: cannot find symbol or error: package system does not existJava does not know that name. Check spelling and capital letters.
Missing closing braceerror: reached end of file while parsingThe file ended while a block was still open.
Extra closing braceerror: class, interface, enum, or record expectedA } appeared when nothing was open, or a misspelled keyword before the class.
Unclosed stringerror: unclosed string literalA text value started with " but the line ended before the closing ".

A sixth common mistake, a wrong main line, behaves differently and gets its own section below. First, each row in a little more detail.

1. ';' expected. The compiler needs a semicolon where the caret points, which is right after the last character of the statement. Add the semicolon. If the caret points at an odd place, such as after a ), look at the whole statement for a missing or extra parenthesis.

2. cannot find symbol / package ... does not exist. Both mean that Java met a name it does not know. Typical causes: a typo (Sytem, printn), a wrong capital (system, System.Out), or a missing pair of quotes around text (println(Hello)). The lines after the first one tell you more. For printn, JDK 21 adds symbol: method printn(String), and for System.Out it says symbol: variable Out with location: class System. For system.out.println("Hello"); JDK 21 says package system does not exist, because Java reads system.out as a package and a class. Both messages point you at the same fix: check the spelling and case of the name under the caret.

3. reached end of file while parsing. You opened a block and did not close it. The caret sits at the last line of the file, so you must look up the file to find the open block. Count braces, as in Lesson 2.

4. class, interface, enum, or record expected. At the top level of a file, Java expects the start of a class (or one of the other type kinds listed). It sees something else. Two causes: an extra } that closes the class too early so the next } is homeless, or a misspelled class keyword. In JDK 21, public Class F7 { (capital C) produced this message plus extra errors about "unnamed classes" being a preview feature. The first error is the one that matters.

5. unclosed string literal. A string literal must close on the same line. Add the closing ". Also check for a stray " inside the text; use \" for a quote that is part of the text.

Not every error comes from javac

A wrong main line is a special case. Consider:

java
public class B4 {
    public static void main(String args) {
        System.out.println("Hello");
    }
}

javac B4.java is silent. The program is valid Java, because a method called main that takes a String is legal. The problem appears when you run java B4: the launcher looks for public static void main(String[] args) and reports that it could not find it. JDK 21 prints:

text
Error: Main method not found in class B4, please define the main method as:
   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application

So the rule from BEG-007 applies: first ask which command printed the message. javac messages are compile-time errors. This one came from java, so it is a launch error, and the message even gives you the line to copy. The same message appears if you write Main instead of main, or leave out static.

Examples

Example 1: a missing semicolon (simple)

java
public class A1 {
    public static void main(String[] args) {
        System.out.println("Hello")
    }
}

javac says:

text
A1.java:3: error: ';' expected
        System.out.println("Hello")
                                   ^
1 error

The caret is just after ). Add ; and recompile. The program prints Hello.

Example 2: wrong case and a typo (practical)

java
public class A2 {
    public static void main(String[] args) {
        system.out.println("Hello");
    }
}

JDK 21 says error: package system does not exist with the caret under the dot after system. Change system to System. In the same program, if the line had read System.out.printn("Hello");, the message would be cannot find symbol and the second line would say symbol: method printn(String), pointing at the misspelled method. Both are the same family of error: Java does not know a name.

Example 3: reading a message about braces and a string (realistic)

A teammate's file has two broken programs. The first:

java
public class A3 {
    public static void main(String[] args) {
        System.out.println("Hello");
    }

reports reached end of file while parsing at the last line. The line shown is the closing brace of main, and the caret sits after it. You know the file ended too early, so you count: two {, one }, so add one } at the end.

The second:

java
public class A4 {
    public static void main(String[] args) {
        System.out.println("Hello);
    }
}

reports unclosed string literal at line 3, with the caret under the opening quote. Add the missing " before ).

Both fixes took under a minute, because the message named the problem. That is the point of the lesson.

Backend Insight

Build tools, test runners, and deployment systems all print messages in the same shape: a file, a line, a description. Whole teams lose time because someone pasted the last line of a long log (often "build failed") instead of the first error. Reading from the first error is exactly the habit this lesson trains.

When you ask for help, a good report includes the exact message text, the file and line, and what you changed last. "It does not work" gives nobody anything to work with. "';' expected at Order.java:12 after I added a line" gets a fast answer. You will use this every time you work with others.

Common Mistakes

Mistake 1: Ignoring the message and guessing

Read the description and the caret before changing anything. A guess can add a second problem to the first.

Mistake 2: Fixing the last error first

Start at the first error. Later ones may disappear once it is fixed.

Mistake 3: Looking only at the reported line

For a missing semicolon, the report often appears at the end of the right line. For a missing brace, the report appears at the end of the file, far from the cause. Use the message as a start, not as a final answer.

Mistake 4: Declaring victory when the compiler is silent

A silent javac only means the file follows Java's rules. A wrong main line, for instance, shows up when you run.

Mistake 5: Not recompiling after each fix

If you change three things and recompile, you will not know which change fixed what. Recompile after every fix.

Exercises

Try each exercise yourself before opening the solutions. Hands-on items must be done on your machine.

Level A: Foundation

A1. List the five parts of a javac error message.

Show solution A1

A1. File and line number, description, copy of the source line, caret, and the error count.

A2. What does ';' expected usually mean? What does unclosed string literal mean?

Show solution A2

A2. The first means a statement is missing its semicolon. The second means a text value was opened with a quote but the closing quote was not found on that line.

A3. Which of these messages comes from javac and which from java? (a) error: cannot find symbol (b) Error: Main method not found in class B4 ...

Show solution A3

A3. (a) javac. (b) java.

Level B: Application

B1. Type the program below, compile it, and write down the message. Then fix it and run.

java
public class Fix1 {
    public static void main(String[] args) {
        System.out.println("Ready");
        System.out.println("Go")
    }
}
Show solution B1

B1. The message is ';' expected at line 5. The fix is System.out.println("Go");. After that it prints Ready and Go on separate lines.

B2. This program has two errors. Predict how many javac will report in the first compile, then compile, fix one at a time, and count the rounds.

java
public class Fix2 {
    public static void main(String[] args) {
        System.out.println("One")
        System.out.printn("Two");
    }
}
Show solution B2

B2. Expect one error in the first compile (';' expected, line 3), because the grammar error stops the compiler before it checks names. After you add the semicolon, a second compile reports cannot find symbol for printn. Change it to println. That is two rounds of fixing, then a third compile that is silent. (Other JDK versions may report both errors at once, so the count can differ.)

B3. Create a program with public static void Main(String[] args) (capital M). Does javac accept it? What happens when you run it, and what does the message tell you to do?

Show solution B3

B3. javac accepts it, because Main is a legal method name. When you run java on the class, it reports that the main method was not found and shows public static void main(String[] args). Fix: change Main to main.

Level C: Challenge

C1. Without compiling, explain the likely cause of each message, and say where you would look: (a) reached end of file while parsing at the last line of a 20-line file; (b) class, interface, enum, or record expected at line 12 of a 12-line file.

Show solution C1

C1. (a) An opening brace is never closed. The report is at the end of the file, so you look upward and count braces. (b) An extra } or a misspelled class keyword near the top. Look at line 12 and also at the line that closes the class before it, and count the braces.

C2. A friend pastes this error and asks "what is wrong?" Write the three questions you would ask or answer first, and the fix.

text
Shop.java:5: error: cannot find symbol
        System.out.println(Price);
                           ^
  symbol:   variable Price
  location: class Shop
Show solution C2

C2. Questions: is Price meant to be text (then it needs quotes, "Price"), is it meant to be a name defined elsewhere (then it is missing a definition), or is it a typo or wrong capital? The message says the compiler could not find a variable named Price at line 5. The most likely beginner fix is to put it in quotes: System.out.println("Price");.

Mini Challenge

Write a "message field guide" for yourself. Take a working Hello program and break it five different ways, one at a time: remove a semicolon, change System to system, delete a closing brace, change String[] to String, and delete the closing quote. For each break, record the command that printed the message, the message text, the line number, and the fix.

Check your work: four breaks are reported by javac, one (the main line) only when you run it, and every program prints Hello once fixed. This guide is the best preparation for the lab.

Summary & Next Lesson

Key takeaways

  • A javac message has a file and line, a description, the source line, a caret, and an error count.
  • Read the first error first, fix one thing, and recompile.
  • The real cause can be on the line above (missing semicolon) or far above (missing brace).
  • The five common messages: ';' expected, cannot find symbol or package ... does not exist, reached end of file while parsing, class, interface, enum, or record expected, and unclosed string literal.
  • A wrong main line compiles and is reported by java when you run the program.
  • A silent javac does not mean the program is correct.

Next lesson

The next lesson, "Demo: fixing five broken programs from compiler messages", walks through five broken programs, one at a time, using this routine. It also prepares the module's lab.

Self-check

  1. Which part of the message tells you the line number?
  2. Why fix the first error before the others?
  3. Where does reached end of file while parsing point, and where is the cause?
  4. A program compiles silently but java says the main method was not found. What do you check?
  5. What does cannot find symbol ask you to check?
Show answers
  1. The file and line at the start of the message, such as Two.java:3.
  2. Later errors can be caused by the first, and some are only visible once the first is fixed.
  3. It points at the end of the file, but the cause is an unclosed block earlier in the file.
  4. The exact main line: public static void main(String[] args), including case and [].
  5. The spelling and capitalisation of a name, and whether text is missing its quotes.

References

  • Oracle, javac command reference, JDK 21. It describes javac as the tool that reads Java source and produces class files. It does not list error message texts.
  • Oracle, java command reference, JDK 21 and The Java Language Specification, Java SE 21, section 12.1.4. They say the launcher calls a main method that must be public, static, void, and take a String array. The text of the "Main method not found" message is not given there.
  • Every error message and its stage in this lesson was produced by compiling and running the examples with JDK 21 on Windows, not taken from an official page. The wording differs between JDK versions, and other versions may report more than one error in the same run. The staging behaviour (grammar errors reported before name errors) is observed from this one JDK, not documented here.

Practice

Apply this lesson with the module's lab, exercises and quiz.

Lab and exercises Quiz

Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.

Continue to next lesson

Type to search levels, phases, modules and lessons.