1.2.5 - Program errors and logic correction
Some programs stop dramatically; others finish calmly with exactly the wrong answer. You will learn to distinguish syntax, runtime and logic errors, then use requirements and state evidence to locate and correct logic errors in written algorithms.
Three error types
The three error types are distinguished by what is wrong and when its effect appears. A precise definition matters more than memorising one example.
Syntax error
A syntax error occurs when code breaks the rules or grammar of its programming language, so the affected statement cannot be parsed or translated correctly.
For example, Python requires a colon after an if condition. The line if score >= 10 breaks that syntax rule. "A spelling mistake" is not a complete definition because some misspelled names still follow Python's grammar.
Runtime error
A runtime error occurs during execution when the computer reaches an instruction it cannot carry out. If the error is not handled, the program stops at that point.
result = 12 / 0 is syntactically valid, but division by zero cannot be completed. Similarly, pritn("Hello") has the valid form of a function call, but the undefined name would cause an error when Python tried to execute it. Runtime refers to when the error occurs, not to a program taking a long time.
Logic error
A logic error is a fault in the algorithm's steps that makes its behaviour differ from the stated requirement. The algorithm can often execute without a syntax or runtime error, but produce a wrong result or fail to terminate as required.
If a rectangle's area is calculated as length + width, the statement is valid and can execute, but the operation does not implement the required calculation length * width.
| Error type | Useful question | Typical evidence |
|---|---|---|
| Syntax | Does the code obey the language's grammar? | A parser or translator reports invalid syntax. |
| Runtime | Can each reached instruction be carried out during execution? | Execution stops when an operation cannot be completed. |
| Logic | Does the algorithm's behaviour match the requirement? | It produces an incorrect result or follows the wrong path, often without an error message. |
Start with the requirement
A logic error cannot be identified just by asking whether code looks valid. You need a precise statement of what the algorithm should do and a supplied input with an expected result.
Consider this requirement:
Award a badge when a learner has 50 or more points.
The correct decision includes 50:
1 points = 50
2 if points >= 50:
3 print("Badge")
For the supplied input 50, the expected output is Badge. Now compare this faulty version:
1 points = 50
2 if points > 50:
3 print("Badge")
The code obeys Python's syntax and every reached instruction can be carried out. However, the condition on line 2 is False when points is exactly 50, so static reasoning predicts no output. That disagrees with the requirement, making this a logic error.
| Evidence | Result |
|---|---|
Required result for points = 50 | Output Badge |
| Predicted result from the faulty algorithm | No output |
| Responsible logic | Line 2 excludes the boundary value 50 |
| Smallest correction | Change > to >= |
| Re-check | 50 >= 50 is True, so Badge is output |
The correction is justified by the requirement, not by guessing which symbol "looks better".
Find the first state divergence
When a logic error is less obvious, follow the values that matter. Compare each predicted state with the state the correct algorithm would need. The first meaningful divergence usually points closer to the cause than the final wrong output does.
This algorithm should total all three activity times in [12, 8, 15] and output 35:
1 times = [12, 8, 15]
2 total = 0
3 for time in times:
4 total = 0
5 total = total + time
6 print(total)
The supplied state comparison is:
| Point reached | time | Faulty total | Required total | Diverged? |
|---|---|---|---|---|
| Before the loop | - | 0 | 0 | No |
| After line 5, pass 1 | 12 | 12 | 12 | No |
| After line 4, pass 2 | 8 | 0 | 12 | Yes |
| After line 5, pass 2 | 8 | 8 | 20 | Yes |
| After line 5, pass 3 | 15 | 15 | 35 | Yes |
Line 4 resets total on every pass, so earlier times are discarded. Line 2 already performs the required one-time initialisation. The smallest effective correction is therefore to delete line 4. Reasoning through the corrected algorithm gives total values 12, 20, then 35.
This method separates the symptom (15 is output) from the cause (the accumulated value is reset on line 4).
Recognise logic-fault patterns
Logic errors often leave a recognisable mismatch between the requirement and the predicted behaviour. The pattern suggests where to inspect, but the requirement still decides the correction.
| Observed mismatch | Inspect | Evidence that reveals the fault |
|---|---|---|
| A value exactly on a limit is treated wrongly | < compared with <=, or > compared with >= | Use the stated limit itself. |
| The first or last item is omitted | Loop start, loop end or range bound | Compare the items required with the items reached. |
| A running result forgets earlier values | Initialisation or a reset inside a loop | Compare the state before and after each update. |
| A numerical result has the wrong size | Arithmetic operator or operand | Work out the required calculation manually. |
| The opposite branch is used | Condition or branch actions | Compare one supplied input with its required branch. |
Here is a worked arithmetic example. An algorithm should calculate the mean of the three scores [6, 9, 12]. Their total is 27, so the expected mean is 9:
1 scores = [6, 9, 12]
2 total = 27
3 mean = total / 2
4 print(mean)
Static reasoning predicts 13.5, so the arithmetic on line 3 is the first divergence from the required calculation. The denominator should be the number of scores. Correcting line 3 to mean = total / 3, or equivalently mean = total / len(scores), gives the required value 9.
Correct and re-check
A correction is not finished when a line has merely changed. Use a disciplined sequence:
- State the exact requirement and the expected result for the supplied input.
- Follow only the values and decisions that affect that result.
- Locate the first point where the faulty state or path differs from the required one.
- Change the smallest amount of responsible logic.
- Follow the corrected algorithm with the same input and confirm that it now meets the requirement.
Do not classify an error from appearance alone. A loop that continues forever can be syntactically valid and may not trigger a runtime error; it is a logic error when termination is part of the requirement and the update moves the state away from that goal.
Syntax asks whether the language rules are followed; runtime asks whether reached instructions can be carried out; logic asks whether the algorithm's behaviour meets its requirement.
Apply that distinction first, then justify a logic correction with the supplied requirement and state evidence.