Even though it's April Fools Day, I didn't want to pull a prank. Instead, I figured I'd use the spirit of the day to write about the thing that often makes us all feel like fools, triggering errors! Everyone has their own approaches for debugging code. However, I think one of the hardest parts of working on something new is developing that approach. This is the order of operations I try and follow when I'm looking for the source of an error in a codebase I'm unfamiliar with.
Compile time or Runtime?
Before I get too far into debugging it's important to discuss the two types of errors you're likely to encounter. Since the goal of debugging is to find the source of your error, keep in mind that there are two distinct points during development that might trigger an error.
Compile Time
Compile time errors are caught early. They are often syntax errors, or file not found errors, etc. If it's a strongly typed language then it may be erring on type mismatch.
error There was a problem parsing "/Users/laurie/Personal/practice/src/pages/index.js"; any GraphQL fragments or queries in this file were not processed.
This may indicate a syntax error in the code, or it may be a file type that Gatsby does not know how to parse.
ERROR Failed to compile with 1 errors 12:39:25 PM
error in ./src/pages/index.js
Syntax Error: SyntaxError: /Users/laurie/Personal/practice/src/pages/index.js: Unterminated regular expression (14:30)
12 | {node.title}
13 | <ul>
> 14 | <li>{node.year</li>
| ^
15 | <li>
16 | {"Characters"}
17 | <ul>
This is an example of a syntax error I triggered by dropping a bracket
You can wait to view compile time errors when you attempt to build your project. However, using an IDE or other text editor with syntax highlighting will often surface compile time errors as you write your code. Try running a linter, look for plugins in your IDE that are focused on the language you're writing in. All of these can help you catch problems before you trigger the associated errors.
Runtime
Runtime errors are the errors that have to do with problems your code encounters when it's actually running. This is the type of error we normally think of as programmers.
Objects are not valid as a React child (found: object with keys {allMarvelYaml}). If you meant to render a collection of children, use an array instead.
in div (at pages/index.js:8)
in main (created by Context.Consumer)
in div (created by Context.Consumer)
in StaticQuery (created by Layout)
in Layout (at pages/index.js:7)
This is an example of an error I triggered in React
The bulk of this post will focus on getting to the bottom of runtime errors.
Error Message and Stack Trace
The first clue that you have a runtime error is typically some combination of a message and an ugly stack trace. This block of text can be in your browser console, in your terminal, in your IDE, in the logs, there are so many options! The first challenge is to find it.
Tip: Look for the source that gave the command to run the code
Once you do that, the content of your error message and the stack trace is a resource. Keep in mind that sometimes the most useful part of these machine responses is hidden. Read past the human friendly message, look a few lines down, see anything helpful?
You're looking for anything you recognize or that helps you map to your own code. Inclusion of a variable name or a line number is useful. If you don't see any of that, and you don't inherently understand what the error message is talking about, that's ok.
Objects are not valid as a React child (found: object with keys {allMarvelYaml}). If you meant to render a collection of children, use an array instead.
in div (at pages/index.js:8)
in main (created by Context.Consumer)
in div (created by Context.Consumer)
in StaticQuery (created by Layout)
in Layout (at pages/index.js:7)
Remember this error message I included above? The indication that our error comes from the index.js file and line 8 is incredibly useful. In this case, it pointed out that I couldn't use an object, I had to use a string or other primitive.
Another thing to keep in mind is that the error message may only be a consequence of your code. The specifics mentioned in the stack trace may not actually point to the root cause. That's why triggering errors can be so complicated to fix!
This error is showing us source code directly! Unfortunately, the source code is not something we wrote, but part of the underlying framework code we triggered.
Time to Break out the Google Machine
Unfortunately, error messages can often be vague, or the stack trace is too deep for us to determine which part of our code is involved. This is when you lean on the world of programmers that have come before you.
Googling errors is about 75% of what a programmer does for a living. I kid, but it often feels that way. Getting good as using google is a legitimate skill, and it has a tremendous impact on your productivity. When googling for the fix to a specific error, there are a few things to keep in mind.
When copying your error message, keep it short and use only the words provided by the underlying code. You're looking to trap as many answers as possible, and using variable names from your specific code won't match with other people who posted about this error.
Include the technology. If you know what layer of your program triggered this error i.e. Javascript v. React include that in your google search terms. Oftentimes you'll find the same error triggered by different technologies, you can eliminate those search results this way.
When googling, the specific words you use matter!
Keep in mind that even if you find someone who encountered the error AND how they solved it, not always a given, you may not understand it, and that's more than ok. New programmers (or even new to this technology programmers) may struggle to understand the answers in these response threads. Without a more thorough understanding of the context of the question it's challenging to work through the technology specific vocabulary. Have heart that it will come with time and there are still other ways to find the solution yourself.
In fact, if you want to see how far you've come go back to a google resource you didn't originally understand a month ago. I bet you will now!
Go Back to the Code
The debugging steps above aren't prescriptive. Sometimes, especially when learning, it's helpful to start here, with your code. Whether you've exhausted the steps above or not, looking at the code is the best way to get to the bottom of how YOU triggered an error.
Start by looking at the most recent lines of code you've added. If you build iteratively and test often this will be easier. Knowing that you had a working project before you added the last 2-3 lines of code makes it simpler to isolate the potential culprit.
If you are in the unfortunate position of having written a lot of code without testing, try stashing your changes, or working backwards. The goal is to find the piece of code causing the issue, then you can focus on fixing it. Commenting things out is another way to isolate the buggy code without deleting progress you plan to add back in later.
Debuggers are your friend...so are break points
Try stepping through your code as it's running. Are the variables assigned to the values you expect to see? Did you go through operations in the order you anticipated?
There are different ways to do this. If you're running javascript you can use the inspector and set break points as your code runs in the browser. If you're in an IDE and running your code directly you can set breakpoints in the IDE itself.
Depending on the project it may be easier to print out the result of your variables, or the fact that you reached a certain point in your code.
getResults(searchString: string): void {
this.githubSearchService.getUsers(searchString) // pull results
.subscribe(result => {
this.result = result;
console.log("I AM HERE!")
if (this.result) {
this.items = this.result.items;
}
});
}
Console logging, or print statements are perfectly valid ways to debug your code.
Still stuck?
Remember, you can always ask for help! It's important to provide as much information as possible when asking your question. Technologies in use, version numbers, including the error and stack trace, etc. If you can set up your code to run in a publicly accessible environment, something like jsfiddle, all the better!
Debugging is a skill and solving errors can be very time consuming and potentially frustrating. However, once you figure it out it's also one of the most satisfying parts of the job!