Reading errors and debugging
Tell compile errors, runtime exceptions and logic bugs apart, and track each one down.
10 min read
You will learn
- Read compiler error codes and messages
- Read an exception and its stack trace
- Find logic bugs with small experiments
- Use breakpoints in a debugger
Bugs are normal
Every programmer, at every level, spends a large part of their time finding and fixing mistakes. The skill isn't writing bug-free code — it's finding bugs quickly. That starts with knowing which of the three kinds you're facing.
| Kind | When you find out | Example |
|---|---|---|
| Compile error | Before the program runs | Typo in a variable name, missing ;, wrong type |
| Runtime exception | While it runs — it crashes | Dividing by zero, index out of range, null |
| Logic bug | Maybe never — it gives wrong results | Wrong formula, <= instead of < |
Compile errors: read the message
The compiler tells you where (line, column), which rule (a code like CS0029) and what went wrong:
(3,13) CS0029: Cannot implicitly convert type 'string' to 'int'
(5,1) CS0103: The name 'totl' does not exist in the current context
(7,22) CS1002: ; expectedTips:
- Fix the first error first. One mistake (like a missing brace) can cause a cascade of confusing follow-up errors.
- Search the code. Searching "CS0029" finds the official explanation and examples.
- In this course's editor, click an error to jump to its line; the red squiggles show the exact spot.
Runtime exceptions: read the type, message and stack trace
When something goes wrong while running, .NET throws an exception. Unhandled, it stops the program and prints something like:
Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Program.<<Main>$>g__CountPositives|0_0(Int32[] numbers) in Program.cs:line 6
at Program.<Main>$(String[] args) in Program.cs:line 19Read it in three steps:
- Type —
IndexOutOfRangeException. The name often tells you the whole story. - Message — what exactly happened.
- Stack trace — the chain of calls, most recent first. Find the topmost line in your code: here, line 6 inside
CountPositives.
Exceptions you'll meet constantly:
| Exception | Usual cause |
|---|---|
NullReferenceException | Using a member of a variable that is null |
IndexOutOfRangeException | Array index < 0 or >= Length |
ArgumentOutOfRangeException | Same idea, for lists, Substring etc. |
DivideByZeroException | Integer division by 0 |
FormatException | int.Parse("abc") |
InvalidOperationException | Calling something at the wrong time (e.g. .First() on an empty list) |
KeyNotFoundException | Reading a missing dictionary key |
You'll learn to handle exceptions with try/catch in Track 3.
Logic bugs: question your assumptions
The program runs, but the answer is wrong. Debugging is now detective work:
- Reproduce it with the smallest input that shows the bug.
- Predict what each step should produce.
- Observe what actually happens — print intermediate values:
foreach (int n in numbers)
{
sum += n;
Console.WriteLine($"n={n}, sum={sum}"); // temporary debug output
}
Console.WriteLine($"sum={sum}, length={numbers.Length}, avg={sum / numbers.Length}");- Where prediction and observation first disagree, that's your bug.
Rubber duck debugging
Explain your code, line by line, out loud — to a colleague or a rubber duck. You'll often hear yourself say the wrong assumption.
Using a debugger
Printing works everywhere, but a debugger is far more powerful. In VS Code (with the C# Dev Kit), Visual Studio or Rider:
- Click left of a line number to set a breakpoint (a red dot).
- Press F5 to start debugging — the program pauses at the breakpoint.
- Hover over variables, or look at the Variables panel, to see their current values.
- Step Over (F10) runs the current line; Step Into (F11) enters the method being called.
- A conditional breakpoint pauses only when a condition is true, e.g.
i == 999.
Key takeaways
- Compile errors: read the location and the
CScode; fix the first one first. - Exceptions: read the type, the message, then the topmost stack trace line in your code.
- Logic bugs: reproduce, predict, observe — print or inspect intermediate values.
- Learn your debugger's breakpoints and stepping; it pays off immediately.
Exercise
This code compiles, but it's buggy. CountPositives crashes, and Average returns the wrong answer for some inputs. Run it, read the exception and the output, and fix both bugs.
C# runtime not loaded
Hint 1
The exception says IndexOutOfRangeException. Which index does the loop reach on its last iteration? Valid indexes go up to Length - 1.
Hint 2
Average({ 1, 2 }) prints 1. Which kind of division happens when both sides are int?
Show solution
int CountPositives(int[] numbers)
{
int count = 0;
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] > 0) count++;
}
return count;
}
double Average(int[] numbers)
{
int sum = 0;
foreach (int n in numbers) sum += n;
return (double)sum / numbers.Length;
}
Console.WriteLine(Average(new[] { 1, 2 }));
Console.WriteLine(CountPositives(new[] { 1, -2, 3 }));Quiz
4 questions · 3 correct to pass1.Which kind of problem is "CS0103 The name 'totl' does not exist in the current context"?
2.In a stack trace, which line usually points to the code you should look at first?
3.The program runs without errors but prints the wrong total. What kind of bug is this?
4.What does a breakpoint do?
To complete this lesson
- ○ Solve the exercise
- ○ Pass the quiz (3/4 correct)