Errors and Debugging

Debugging starts by identifying what kind of error you are dealing with. Different error types produce different symptoms and require different fixes.

You can read this note directly if you know basic Python if statements, functions, and assertions. The main beginner skill is to describe what happened before trying to fix it.

Caption: Syntax errors prevent parsing, runtime errors occur during execution, and logic errors produce incorrect results.

Quick Diagnosis

SymptomLikely error type
Python reports invalid syntax before normal execution beginssyntax error
the program starts, then stops with an exceptionruntime error
the program finishes, but the result is wronglogic error

This is only a first diagnosis. A complete answer should also identify the faulty line or condition and explain the correction.

Syntax Errors

A syntax error occurs when code breaks the grammatical rules of Python, so Python cannot parse it successfully.

Example:

if mark >= 50
    result = "Pass"

The colon is missing after the condition. The program cannot run until the syntax is fixed.

Correct version:

if mark >= 50:
    result = "Pass"

Other common causes include:

  • unmatched brackets or quotation marks;
  • incorrect indentation;
  • misspelt keywords;
  • missing commas or colons where required.

Beginner debugging tip: inspect the line before the highlighted line as well. The reported location may be where Python finally detects the problem rather than where it began.

Runtime Errors

A runtime error occurs after execution has started.

Example:

age = int("abc")

Python can parse this code, but converting "abc" to an integer raises a ValueError.

Other examples include:

result = 10 / 0
item = values[20]

These can raise ZeroDivisionError and IndexError respectively.

Handling Predictable Exceptions

Exception handling lets a program respond to a predictable runtime problem instead of crashing.

def read_int(text):
    try:
        return int(text)
    except ValueError:
        return None

Example use:

age = read_int("abc")
 
if age is None:
    print("Invalid age")

Catch specific exceptions where possible. A broad or bare except can hide unrelated bugs and make debugging harder.

Exception handling does not make invalid data valid. It only controls how the program responds to the error.

Logic Errors

A logic error occurs when the program runs but produces the wrong output or behaviour.

Example:

def is_pass(mark):
    return mark > 50

If the pass mark is 50, the comparison is wrong because 50 should pass.

Correct version:

def is_pass(mark):
    return mark >= 50

Logic errors do not usually produce an exception message, so they are often found through tracing and carefully chosen test cases.

markBuggy mark > 50Correct mark >= 50
49FalseFalse
50FalseTrue
51TrueTrue

The extreme value 50 exposes the fault.

Debugging Workflow

Caption: Debugging is an iterative cycle: reproduce the failure, isolate its cause, make one focused correction, and retest.

Use this workflow:

  1. Reproduce the problem with one specific input.
  2. State the expected behaviour.
  3. Record the actual behaviour or exception.
  4. Trace values and control flow near the failure.
  5. Isolate the smallest faulty section.
  6. Change one cause at a time.
  7. Retest the failed case.
  8. Retest related normal, abnormal, and extreme cases.

Changing several parts at once makes it difficult to know which edit fixed the fault or introduced a new one.

Trace Example

Buggy code:

def valid_mark(mark):
    return 0 < mark < 100

Expected rule:

Marks from 0 to 100 inclusive are valid.

Trace for mark = 0:

ExpressionValue
0 < markFalse
mark < 100True
whole expressionFalse

The implementation excludes both valid boundaries.

Correct version:

def valid_mark(mark):
    return 0 <= mark <= 100

Retests:

assert valid_mark(0) is True
assert valid_mark(50) is True
assert valid_mark(100) is True
assert valid_mark(-1) is False
assert valid_mark(101) is False

Paper 1 and Paper 2 Emphasis

For a written explanation, be ready to:

  • classify an error as syntax, logic, or runtime;
  • explain the symptom;
  • identify the cause;
  • describe the correction.

For practical work, be ready to:

  • reproduce the bug;
  • read exception messages;
  • trace variable values;
  • make a focused correction;
  • rerun appropriate test cases.

Common Mistakes

  • Calling an incorrect answer a syntax error.
  • Assuming code is correct because it runs without crashing.
  • Treating all exceptions as the same type of error.
  • Catching every exception and hiding the real cause.
  • Changing many lines without isolating the fault.
  • Retesting only the failed input and ignoring nearby boundaries.

Check Your Understanding

  1. Which error type is caused by a missing colon?
  2. Which error type is raised by int("abc")?
  3. Which error type is caused by using > instead of >=?
  4. Why should a fixed boundary bug be retested with nearby values?

Answers:

  1. Syntax error.
  2. Runtime error.
  3. Logic error.
  4. Nearby values check whether the revised condition handles both the boundary and surrounding cases correctly.