Viewing Options


Skip navigation Stay up to date and informed on the latest goings on here at Nathan Tech.
Subscribe to our newsletters!

Debugging with a screen reader

Your program has crashed and the screen reader has just delivered six seconds of punctuation, filenames and indignation.

Good. You have evidence.

Debugging is not the art of staring at code until guilt causes the bug to reveal itself. It is the process of narrowing down what happened, where it happened and what assumption turned out to be wrong.

Do not start by reading everything

A traceback or compiler log may contain dozens or hundreds of lines. Most of them are context, not the first thing you need.

Start by looking for:

Do not heroically read 700 lines from top to bottom. Search. Words such as error, exception, failed and the name of your source file are useful anchors.

Tracebacks: read from the useful end

Many Python tracebacks end with the exception type and message. Start there, then work backwards until you reach code you recognise.

Traceback (most recent call last):
  File "example.py", line 18, in load_project
    value = settings["missing"]
KeyError: 'missing'

The useful first facts are: this is a KeyError, the missing key is missing, and your code reached the problem at line 18 of example.py.

You can investigate the rest after you know what question you are asking.

Use screen-reader review instead of disturbing the program

If the error appeared in a terminal, use the techniques in Using the command line with a screen reader.

With NVDA, review the output independently of the live caret. With JAWS, use the JAWS Cursor or Virtualize Window. Copy the useful section into an editor if the terminal is becoming awkward.

Do not make yourself reread a hostile moving interface merely because that is where the error originally appeared.

Logs are evidence, not literature

Logs are usually meant to be searched.

If the application writes a log file, open it in an editor where your screen reader has predictable navigation. Search for the time the problem occurred, an error level such as ERROR or CRITICAL, or the feature you were using.

A useful log answers questions: what was the program trying to do, what went wrong and where? It should not answer a fourth question called "what was the user's password?" Keep secrets and tokens out of logs.

Reduce the problem

If opening one enormous project crashes the program, try a small project.

If importing ten files fails, try one.

If a function receives twelve arguments, test the suspicious value separately.

Every reduction removes possible causes. A five-line example that fails in the same way is much easier to reason about than the entire application.

Print debugging is not beneath you

A strategically placed print or log statement can answer useful questions:

print("selected path:", path)
print("items found:", len(items))
print("about to load settings")

Do not scatter 400 unlabeled values across the console. Label them so speech tells you what you are hearing.

Once the bug is understood, remove temporary noise or turn useful diagnostics into proper logging.

Breakpoints can be useful, but only if the debugger is usable

A graphical debugger can pause execution, inspect variables and step through code. That is powerful when its controls and variable views work well with your screen reader.

If your IDE's debugger turns variable inspection into an accessibility obstacle course, you are not morally required to use it. Logging, small reproductions, command-line debuggers and targeted tests are legitimate debugging tools.

Do not fix the first thing that makes the error disappear

Commenting out the crashing line may stop the crash. It may also stop the program doing its job.

Ask why the bad value reached that line. Was input invalid? Was a file missing? Did an earlier operation fail? Is the code assuming something that is not guaranteed?

The error location tells you where the problem became visible. The cause may be earlier.

Keep a useful bug report

If you need help from somebody else, give them something they can work with:

"It doesn't work" is technically a bug report. It is merely one with a promising future in archaeology.

A practical debugging loop

  1. Reproduce the problem.
  2. Capture the useful error.
  3. Find the first relevant location in your code.
  4. Reduce the failing case.
  5. Inspect or log the values involved.
  6. Change one thing.
  7. Run the same test again.
  8. Once fixed, test nearby behaviour so the repair has not created a new problem.

Debugging becomes much less mysterious when you stop treating the error as a verdict and start treating it as data.


Continue learning

Using the command line with a screen reader covers reviewing live terminal output with NVDA and JAWS.

Screen-reader testing moves from debugging your own workflow to testing the accessibility of the software itself.


Back to Developer Central

Return to the Developing with a screen reader learning path.

Back to the top

Thank you for visiting!

Thanks for visiting this page. Please tell your friends about us!

Share Nathan Tech on Twitter/X


This page has been viewed 32 times since November 3rd, 2018.

Why not follow us on Twitter/X: @NathanTech7713


Recently viewed products

Products other visitors have looked at recently:


Nathan Tech

It's not disability

It's ability!

Last updated Saturday 12th April 2025 21:06:37

Copyright © 2013-2026 Nathan Tech. All rights reserved.