Skip to content
Happy Programming Guide
Start learning
Debugging & Errors

Syntax Errors vs Logic Errors vs Runtime Errors

The three kinds of programming error, how to tell them apart from the way they fail, and the different technique each one needs to find and fix.

Close-up of a ladybug on a metal surface

Every bug you will ever write is one of three kinds. A syntax error is code the language cannot read, caught before anything runs. A runtime error is code that reads fine but crashes when a particular line executes. A logic error is code that runs without complaint and produces the wrong answer. They fail differently, they are found differently, and knowing which one you have is the first step of every debugging session.

The three, side by side#

Syntax error Runtime error Logic error
What went wrong The code breaks the language’s grammar An operation could not be performed The code does what you wrote, not what you meant
When it shows Before the program runs While running, at a specific line Never, on its own
Message Yes, with a line number Yes, with a stack trace No
Example Missing bracket Dividing by zero Off-by-one in a loop
Found by The compiler or interpreter Running it, or tests Tests, or a user

Syntax errors#

Python
def total(items)
    return sum(items)
# SyntaxError: expected ':'
JavaScript
const names = ["a", "b";
// SyntaxError: Unexpected token ';'

The language cannot even parse the file, so nothing runs. The message names a line, and the real mistake is on that line or the one before it — a missing closing bracket on line 10 is often reported on line 11, where the parser finally realised something was wrong. Common causes: unbalanced brackets or quotes, a missing colon or semicolon, a misspelt keyword, and in Python, inconsistent indentation.

These are the easiest errors. The editor underlines them as you type, and one fix makes the message go away. If several appear at once, fix the first; the rest are often consequences of it.

Runtime errors#

Python
def average(numbers):
    return sum(numbers) / len(numbers)

average([])
# ZeroDivisionError: division by zero

The code is valid and ran up to a point. Then an operation was impossible: dividing by zero, opening a file that does not exist, reading a property of nothing, calling a method that does not exist on that type. The program stops and prints a stack trace: the error type, a message, and the chain of function calls that led to the line.

Read the trace from the bottom up. The last line is the error; the lines above show where it happened and what called that. The bug is often not on the line that failed but in whatever produced the bad value — here, whoever passed an empty list.

Runtime errors depend on input. The same function works on a list of five numbers and crashes on an empty one, which is why they slip past a quick manual test and appear in production. The types you will meet most, across languages:

  • Null or undefined access: using something that has no value.
  • Type errors: an operation on the wrong kind of value.
  • Index out of range: asking for item 10 in a list of 5.
  • Key or attribute not found: a name that does not exist on the object.
  • I/O and network: files, permissions, connections.

Logic errors#

Python
def average(numbers):
    return sum(numbers) / len(numbers) + 1      # runs perfectly; answer is wrong

def is_adult(age):
    return age > 18                             # 18-year-olds are excluded; should be >=

No message, no crash. The program does exactly what the code says, and the code says the wrong thing. Off-by-one errors, wrong comparison operators, conditions that are the wrong way round, a loop that stops one iteration early, the right formula with the wrong variable.

These are the hardest, because the computer thinks everything is fine. They are found by comparing what the program produced with what it should have produced — which means you need to know the right answer for some input. That is what tests are: a set of inputs with known correct outputs, run every time.

Finding a logic error#

  1. Get a failing case. One specific input where the output is wrong. Make it as small as possible.
  2. Predict, then check. Before each line, write down what the variables should be; then print or inspect them. The first place prediction and reality disagree is the bug.
  3. Bisect. If the function is long, check the midpoint. Right there? The bug is later. Wrong? Earlier. Repeat.
  4. Read it aloud. Explaining the code line by line to someone, or to nobody, catches a surprising share of wrong conditions.

A debugger does step 2 without the prints: set a breakpoint, step through, watch the values.

Preventing each#

Kind Prevention
Syntax An editor with a language extension; a formatter; running the code often
Runtime Type checking; validating input at the edges; handling the cases that can fail (empty, missing, null)
Logic Tests with known answers; small functions; code review; a debugger

Compiled and statically typed languages move some runtime errors to compile time: a type mismatch in Java or C# is reported before the program runs. That is a large part of why those languages, and TypeScript and typed Python, are used for big systems.

Questions people ask#

Is an exception the same as a runtime error?

An exception is how most languages represent a runtime error: an object describing what went wrong, which stops the program unless caught. The terms are used interchangeably in practice.

Are compile errors syntax errors?

Syntax errors are one kind of compile error. Compilers also report type errors and undeclared names, which are not grammar problems but are still caught before running.

What is a semantic error?

Another name for a logic error: the code is grammatically valid but means the wrong thing.

Which kind do professionals spend the most time on?

Logic errors, by far. Syntax errors take seconds; runtime errors take minutes; a subtle logic error in production can take days. That is why tests and code review exist.

Where to go next#

How to read a stack trace, bottom to topRead next

Keep reading

Keep going — pick your next guide

The fastest way to improve is to read one guide, then build the thing it describes. Start with the basics, or jump straight to a project.

Ask a question or share what worked

Your email address will not be published. Required fields are marked *