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!
Top comments (7)
Sometimes a simple error makes me stuck in 1 or more hours, for example like javascript maximum stack exceeded, in the console is shown the stack trace but when I click I don't know where it's come from, but actually you should search in the stack trace which one is the script you know or you had been write, in my case it's
main.js
so click onmain.js
and it will point out which part you must fix.Thank You @Vico, For Pointing This issue, It's Really A Huge Issue That Have Been Out There,
If You Can Make Post On It Clarify it more would be awesome
Also, crystal clear instructions for replication are the most valuable asset when fighting a nasty bug. Nothing is worse than the issues which magically go away whenever you call your coworker to come take a look at this. Also, see if you can isolate the code and still trigger the error - if you can extract part of your code into a smaller demo that triggers the error, it will be much easier to share with co-workers and vendors and decrease the surface area you must investigate.
I am also a fan of APM tools like Raygun or New Relic or elmah.io. Learning about errors from your users without them having to tell you is incredibly valuable, and many of these tools will look for correlations between errors to help you find the source and some can even predict how high of a priority the bug is in terms of lost customer interactions.
Hey Laurie, thanks for sharing. Could you add the #javascript or #node to the post.
I hit the 4 tag limit :/ But changed out programming for javascript!
Thanks, I read the title and was definitely curious but unsure about the programming language.
I think a lot of the advice here is relevant to debugging across programming languages. Or at least that's the goal! However, the examples are definitely in javascript.