I Never Touched His Keyboard: Teaching Kids to Debug

Michael Murr··8 min read

Last updated: September 2026

Teaching kids to debug is the part of coding tuition that separates a tutor from a video course, and it is almost entirely about what the adult refuses to do. A child stares at broken code. The fastest route is for me to lean in and fix it. The route that teaches is a question, then silence, then another question.

Last month I sat through a student fixing five bugs in his own program. I never touched his keyboard once. It took about four times longer than fixing it myself would have, and it is the only reason he can now fix the sixth one without me.

Key Takeaways

  • Fixing a child's code for them removes the exact experience that builds debugging ability.
  • The method is a question aimed at the gap between what they expected and what happened.
  • Expect it to take three to five times longer than doing it yourself. That time is the lesson, not overhead.
  • Naming the error type out loud ("that is an off-by-one") gives a child a label they can search and reuse.
  • The goal is not working code. It is a child who catches the next one unprompted.

Why fixing it for them is so tempting

Everything about a lesson pushes toward fixing it yourself. The clock is running. The child is frustrated. You can see the problem in two seconds, and pointing at it feels like teaching because you get to explain the concept afterwards.

It does not work. The explanation lands on a child who is no longer trying to solve anything, because the problem is gone. They will nod, they will follow it, and the next time the same error appears they will be exactly as stuck.

Debugging is not knowledge. It is a procedure: read the output, compare it to what you expected, form a guess about which line caused the difference, change one thing, run it again. That last part matters, and Python's own guide to errors and exceptions is worth a child's time once they can read a traceback. You cannot transfer a procedure by describing it. The child has to run the procedure while someone keeps them pointed in the right direction.

That is the whole job. Keep them pointed, do not walk it for them.

Five bugs, five questions

Here is what it looked like in practice, on a multiplication table my student had written from a blank file. Five separate faults, none of which I fixed.

1. The separator lines in the wrong place

His row separators were printing after every number instead of after every row, so the output looked like confetti.

I asked where he wanted the dashes to appear. He said after each row. So I asked what decides which loop a line belongs to, and he got there: it was an indentation level, not a logic problem at all.

This is the most valuable class of bug to hand back, because the child's mental model is correct and only the placement is wrong. Fixing it for them removes a thirty-second win.

There is a general rule underneath it. When the output is nearly right, the bug is almost always structural rather than logical, and structural bugs are the ones children can find unaided. A program producing complete nonsense usually needs help. A program producing the right things in the wrong arrangement almost never does.

So my first question when I see nearly-right output is never about the logic. It is some version of "which part of this is running more often than you wanted?"

2. The variables nobody could read

He was printing two similarly named values side by side, and the output was genuinely hard to follow even though it was arithmetically right.

What I said was that I knew the answer and was still confused reading it, then asked what would make it clearer. That framing matters. Telling a child their naming is bad is a criticism. Telling them that an experienced reader cannot follow it is a fact about the code.

He renamed it himself. Readability is not a correctness issue, which is exactly why it is worth spending a question on rather than a correction.

3. The number that ran to eighty

He had written range(1*1, 9*9) and the output was climbing past 80 when it should have stopped at 9.

I asked what was pushing that number so high. He traced it to the range. Then he worked out that 9 times 9 is 81, and that the range was doing arithmetic he had not intended.

We ended up with a rule he stated himself: do not compute inside a range, even though Python lets you. That rule came out of the failure, which is the only reason it stuck.

This one is worth dwelling on because it is a bug that is not an error. range(1*1, 9*9) is completely valid Python. Nothing is underlined, nothing throws, and the program runs happily. It just does something other than what he meant.

Children find this category genuinely unsettling the first time, because up to that point their model has been that mistakes produce red text. Learning that a program can be wrong and silent at the same time is a real step, and it is the beginning of understanding why you test things rather than just running them once and moving on.

The teaching move is to name the category out loud: this is not an error, it is a program doing exactly what you asked instead of what you wanted. Then let them sit with the difference for a moment.

4. The missing last row

The table stopped one row short.

One question: should that stop at 9 or at 10? He connected it back to the rule he had met twice before, that range() counts up to but not including the number you give it.

This is the bug I would most want a child to hit early, and hit repeatedly.

The reason is that off-by-one is not really about range(). It is about the general habit of checking the boundaries of anything rather than the middle. A loop that works for the first item and the last item almost always works for everything between them, and children who learn to check the ends early become much faster at finding their own faults later.

It is also the most reliably teachable bug there is, because the symptom is so specific. One row missing, one item too many, the last thing never happening. When a child can name that symptom on sight and go straight to the range, they have acquired a diagnostic rather than a fact.

He had met the rule twice before this session and still tripped on it. That is normal and it is worth saying to parents plainly: two or three encounters is the usual cost of internalising it, and each one has to be a bug they fixed rather than a rule they were told.

5. The second loop with the first loop's name

His inner loop reused the outer loop's variable, and the output collapsed.

I asked how many loops there were, and then how many names. He answered his own question in the gap between the two.

Then a sixth thing happened, which is the only one that really counted. He hit the same off-by-one error again, this time on the inner loop, and before I said anything he spotted it and fixed it himself.

That is the return on the whole hour. Not the table.

Worth noticing what the five questions have in common. None of them contains a diagnosis. Each one points at the gap between what he expected and what appeared, and then stops talking. The silence after the question is doing as much work as the question is, and it is the part adults find hardest, because a child thinking looks identical to a child stuck for the first few seconds.

The other thing they share is scale. Each question targets one fault. I never asked him to look at the whole program, because "what is wrong with this" is not answerable by someone who does not yet know what right looks like.

The question that does the work

Most useful debugging questions are a version of one question: what did you expect, and what actually happened?

Almost every bug lives in the gap between those two answers, and children are rarely asked to state either one. They look at the wrong output and feel that it is wrong without articulating why. Forcing the comparison into words usually locates the fault before I have to say anything else.

The follow-ups are narrow on purpose:

  • "Which line do you think produced that?"
  • "What is pushing that number that high?"
  • "You changed two things. Which one do you think did it?"
  • "Read me line four out loud."

Notice that none of them contain the answer. Notice also that none of them are "any ideas?", which is a question that gives a stuck child nowhere to go.

There is a second thing worth doing at the same time: name the error type out loud. When he stopped at 9 instead of 10, I told him plainly that this is called an off-by-one error and that it is the most common mistake in Python. Now he has a label. He can search it, recognise it, and say it to himself the next time a loop comes up one short. Labels turn a one-off fix into something reusable.

One parent of a son learning Python put it in terms of the challenges: they take you from zero upward, and the challenges themselves are what help. The challenges are the mechanism. A challenge is just a controlled way of producing bugs that the child then has to own.

When you should just tell them

This method has a failure mode, and it is worth being honest about it, because I have got this wrong.

If you keep asking questions past the point where a child has any route to the answer, you are not teaching, you are applying pressure. A question only works if the knowledge needed to answer it is already in their head. When it is not, the child reads the repeated questioning as "I am supposed to know this and I do not", and their confidence takes a hit that costs more than the bug was worth.

So the rule I use:

SituationWhat to do
They have the knowledge but have not connected itAsk. This is the whole method.
They have never met the conceptTell them, clearly, then set a challenge that uses it
They have guessed three times with no progressNarrow the question hard, or give them the line and ask why
They are visibly upsetStop, fix it together, come back to it next session
The bug is environmental, not theirsFix it yourself and move on, it teaches nothing

That last row matters more than people expect. If a notebook kernel will not start or an extension is misconfigured, there is nothing in it for the child. Fix it, apologise for the time, get back to the actual work. Once a child is ready for real tooling, VS Code's Python debugger turns a lot of guesswork into something they can watch happen.

For more on how frustration itself should be handled, I have written a separate piece on when coding makes kids upset.

How parents can use this at home

You do not need to know Python to do this. You need to be able to ask two questions and then tolerate a silence, which is harder than it sounds.

When your child says the code is broken:

  1. "What did you expect it to do?"
  2. "What did it actually do?"
  3. Wait. Do not fill the gap.

That is genuinely most of it. You are not diagnosing the bug, you are making them state the comparison, which is the step they skip. A surprising number of bugs get solved by the child in the middle of answering question two.

What to avoid: reading the error message for them, taking the mouse, or saying "did you try turning it off and on". If you cannot help further, "show me what you have tried so far" keeps them working without you supplying anything.

If your child is at the stage of following tutorials without producing anything independently, the piece on the first time a student writes code from scratch covers what that transition looks like.

Frequently Asked Questions

Should I fix my child's code when they are stuck? Not usually. Ask what they expected and what happened instead, then wait. Fix it directly only when they have never met the concept, when they are genuinely distressed, or when the problem is environmental rather than something they wrote.

How long should I let a child struggle before helping? Until they have made three real attempts, or until the frustration stops being productive, whichever comes first. Struggle with a route forward builds skill. Struggle with no route forward just teaches a child that coding makes them feel stupid.

What is the most common bug for kids learning Python? The off-by-one error, caused by range() stopping just before the number you give it. Python's documentation describes it as a half-open interval. Most children need to hit it two or three times before it sticks.

My child gets angry when I ask questions instead of helping. What now? That usually means the questions are aimed above what they know. Narrow them sharply: "read me line four out loud" is easier to answer than "what do you think is wrong". If it is still going badly, solve it together and set a similar challenge next time.

Is this different from how a coding class teaches debugging? Substantially. In a group, a stuck child is usually unblocked as fast as possible so the class can move on, which means someone supplies the fix. The questioning approach takes too long to run for twelve children at once, which is one of the real differences 1-on-1 buys.

Can AI coding tools do this for a child? They can fix the bug instantly, which is the problem. Used well, an AI tool is a fast explainer once the child has already tried. Used as a first move, it replaces the exact struggle that builds the skill.

The Bottom Line

The point of a debugging session is not the working program at the end of it. It is the child catching the next error alone, in a bedroom, on a Tuesday, with nobody watching.

Getting there costs a lot of adult patience and a lot of silence, and it looks slow while it is happening. It is the highest-return thing I do in a lesson.

I teach kids ages 8 to 16 online, 1-on-1, and this questioning method is most of what a session actually is. Book a free Discovery Call.

Enjoyed this article?

Your child can learn this and more with a dedicated 1-on-1 tutor.

Book a Free Discovery Call