Debugging logic errors
Finding the mistake that gives no message: watching, printing, stepping and common bugs.
Covers OCR J277 2.3.2 Testing · AQA 8525 3.2.11 Robust and secure programming · Edexcel 1CP2 6.1.2 Read, write, analyse and refine programs · Edexcel 1CP2 6.1.5 Finding and correcting errors
Do this lesson in the simulatorPrint it: worksheet (PDF) · answers (PDF) · as a web page
Syntax errors and runtime errors announce themselves. A logic error does not: the program runs, finishes, and does the wrong thing. Finding one is detective work, and like detective work it goes faster with a method. This lesson is that method, and the tools that help.
Step 1: know what should happen
You cannot find a mistake until you know exactly what right looks like. This program should drive a square of 20 cm sides clockwise, turning right at each corner, and end where it started, facing the way it began:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
side = 20
for i in range(3):
forward(60, distance=side)
turn_left(30, angle=90)
print("back at", position(), "facing", round(heading()))
Run it. It ends in the wrong place, facing the wrong way. No error message. The trail on the mat is the first clue: count its sides.
Step 2: find where it first goes wrong
Look for the first moment the program does something different from what it should. Everything before that point is fine, and the bug is at or just before it. Three ways to find that moment:
- Watch it. The trail shows three sides, not four, and each turn goes the wrong way.
- Print it. Add a
printinside the loop showingi,position()andheading()each time round: the program writes its own trace table. - Step through it. Press Debug. The program stops before each line; press Step to run one line at a time, and read the variables beside the editor as they change.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
side = 20
for i in range(3):
print("side", i, "starts at", position(), "facing", round(heading()))
forward(60, distance=side)
turn_left(30, angle=90)
print("back at", position(), "facing", round(heading()))
The printout shows i going 0, 1, 2: only three times round. And the heading goes to about 270, then about 180: anticlockwise, when the brief says clockwise, which would take it to 90, then 180.
Step 3: form a theory and test it
Say what you think is wrong, change one thing, and run again:
- Theory:
range(3)gives three sides. Change it torange(4). Run: four sides now, and it ends back at the start, but the square is drawn to the left of where it began, anticlockwise. Ending in the right place is not the same as meeting the brief. - Theory:
turn_left(30, angle=90)turns anticlockwise. Change it toturn_right(30, angle=90). Run: a square, back at the start.
Changing one thing at a time matters. Change both at once, and if the result is still wrong, you do not know which change helped and which did not.
Common logic errors
| Error | Example | How it shows |
|---|---|---|
| Off by one | range(3) for four things |
one too few (or too many) times round |
| Wrong operator | < instead of <= |
the edge case, exactly at the limit, is wrong |
| Wrong sign | turn_left(30, angle=90) for turn_right(30, angle=90) |
the robot goes the opposite way |
| Reset in the loop | total = 0 inside the loop |
a total that never grows |
| Wrong variable | print(side) when you meant total |
the right kind of value, but the wrong one |
| Order of steps | reading the sensor before driving, when it should be after | values that lag one step behind |
Most bugs are one of these. When a program is wrong, run down the list.
Explaining it out loud
Programmers sometimes explain their code, line by line, to a rubber duck on the desk. It sounds silly, and it works: saying what each line should do makes you notice the line that does not. A classmate works even better than a duck.
Task: fix the square
This program should drive a square of 25 cm sides clockwise, turning right at each corner, and finish back at the start, facing the way it began. It has three logic errors. Find them with the trail, prints or Debug, and fix them one at a time.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
side = 25
for i in range(3):
side = 20
forward(60, distance=side)
turn_left(30, angle=90)
Challenges
- Write a program with an off-by-one error in it for a partner, and time how long they take to find it with Debug.
- The parking sensor from F2.8 stops too close to the wall at high speed. Is that a logic error? How would you find the best stopping distance?
- Add a
printthat shows a variable's value and its type. When would the type be the clue?
Past paper questions on this
Real exam questions that test this, each worked through with a program you can run.
- AQA 8525 June 2025 Paper 1, Question 9: Which of five algorithms correctly total an array 2 marks
- AQA 8525 June 2023 Paper 1, Question 10: Trace nested FOR loops over a list of scores and find the error 6 marks
- AQA 8525 June 2023 Paper 1, Question 11: Normal, erroneous and boundary test data, and a logic error 5 marks
- AQA 8525 June 2022 Paper 1, Question 5: A syntax error and a logic error in a random number program 5 marks
- AQA 8525 Sample Paper 1, Question 15: Fix a loop that prints odd numbers so that it works for negative input 4 marks
- AQA 8525 Sample Paper 1, Question 17: The highest common factor program that fails for 4 and 4 3 marks
- OCR J277 June 2024 Paper 2, Question 3(a), (b): Define a syntax error, then correct two logic errors in a range check 6 marks
- OCR J277 June 2023 Paper 2, Question 2: Syntax and logic errors: correct a loop that should total an array 6 marks