RailsConf 2023

Don’t be afraid of the scary red error messages; they’re actually our friends

Don’t be afraid of the scary red error messages; they’re actually our friends

by Shana Moore and Kait Sewell

In their talk "Don't be afraid of the scary red error messages; they're actually our friends," Shana Moore and Kait Sewell at RailsConf 2023 delve into the significance of embracing failures, errors, and tests in software development. The presenters aim to shift the audience's perspective on error messages, advocating for a mindset that views failures as opportunities for learning and growth instead of as setbacks.

Key points discussed include:

  • Normalization of Failure: Sharing failures openly is essential in programming, as it promotes a growth mindset. The speakers stress that failures are common and should be regarded as learning experiences, which is a skill that can be cultivated.

  • Cognitive Triangle: They introduce the concept of the cognitive triangle, emphasizing that changing one’s feelings towards failure can alter thoughts and actions positively.

  • Practical Methods to Handle Errors: Kait presents nine practical tips to handle error messages, including reading and understanding error outputs, using stack traces to identify problems, and utilizing debugging tools like Pry and the built-in debugger to step through code.

  • Common Errors: The discussion covers frequent problems developers encounter, such as syntax errors, incorrect inputs, and logical errors. The presenters highlight the value of Test Driven Development (TDD) to catch these issues early and ensure the code behaves as expected.

  • Utilizing Online Resources: They encourage developers to seek help from community resources such as Stack Overflow and documentation websites. Additionally, AI tools like ChatGPT can provide valuable guidance, although caution against reliance on them is advised.

  • Encouragement to Ask for Help: Finally, the speakers underscore the importance of collaboration within teams, encouraging developers to share their error messages and solutions to create a supportive environment.

The conclusion of the talk reinforces the notion that embracing failures can lead to more robust code and increased confidence among developers. By fostering a positive relationship with errors, developers can enhance their skills and deliver higher quality work, ultimately benefitting their teams and clients.

00:00:20.840 Thank you for being here for our talk, "Don't be afraid of the scary red error messages; they're actually our friends."
00:00:28.080 We're here to change your mind about failure, how you respond to it, and give you some tips and tools for how to deal with it in your own programming adventures.
00:00:40.620 In my first stand-up with a brand new client, imagine this client is a very posh one. I mean there’s a lot of argyle and tweed involved. This is what I showed them in my first stand-up. It was my turn to share, and I said, "Alright, everybody, this is the big Rails error page I'm currently contending with. I plan to figure out what's going wrong," and then I stopped sharing. We moved on with stand-up.
00:01:06.060 Later, after the meeting, my project manager came to me and said, "That was amazing!" I was puzzled and asked, "What was?" because I had no idea what he was talking about. He pointed out that I had shared my issues openly, unlike everyone else, who had basically said, "No blockers," and we moved on. I was doing things differently.
00:01:19.740 You see, I grew up as an artist, and so failure has actually been my end goal. Aha! Another artist in the crowd, I can tell. Many of you might not know this, but the starving artist stereotype is pervasive; it is what all budding artists are told to expect from their careers.
00:01:33.960 I didn't realize that my unabashed nature when it came to failure would become such a blessing when I transitioned into being a software engineer. What I've learned from this journey, from junior to senior level, is that the skill of openly sharing one's progress, including the failures, is not common, but it can be taught. In this talk, we'll tackle how to normalize failure and then give you some tips on how to handle them in your own practice.
00:02:10.200 We'll have some time at the end for questions, so if you think of any, please save them till the end. Thanks! Failures, errors, and broken tests are a natural part of the development process. This talk is all about how to embrace them rather than fear them, and how to turn these hurdles in your path into stepping stones to get you where you want to go.
00:02:36.900 My name is Kait Sewell, and I’m a senior software engineer at scientist.com. We help make digital ideas a reality and are primarily a Rails shop with some React, JavaScript, and Docker-based environments. Soft Serve is the software consultancy of scientist.com and we’re in a rare opportunity where we're looking to bring on some bigger clients.
00:03:01.440 Scientist.com is a company that helps researchers get science done on demand, and my colleague and I work for the Department that assists our clients with their software engineering needs. This is Shayna Moore; she's a more experienced senior software engineer, and you all are lucky to get to listen to her speak later.
00:03:38.580 The first thing I want to do is normalize failure. Handling error messages is just one aspect of dealing with failures in software development. Failures can occur at various levels of the development process such as design, implementation, testing, or deployment. Dealing with failures effectively requires a mindset that views failures as opportunities for learning and improvement, rather than as sources of blame or shame.
00:04:09.180 To overcome this, one must embrace a growth mindset. I encourage you to see failures as opportunities for growth, not as personal flaws or setbacks. A failure is not a waste of time; it is an experience where hopefully you learned something. Even experienced programmers make mistakes; the key is to learn from these failures and use that knowledge to improve.
00:04:37.740 The problem we face is that for most people, sharing failure is incredibly uncomfortable. When it comes to what we share openly, we tend to highlight our successes on social media rather than mundane tasks like a trip to the grocery store. This is where we have to recondition ourselves to see failure in a new light. Rewiring your brain is not easy, but it's doable.
00:05:11.220 All sorts of books have been written about how to hack your brain and retrain it. What I'm asking from you is to lean into the idea of the cognitive triangle: if you change your feelings about something, you can change your thoughts about it, and if you change your thoughts about it, you can change your feelings about it, which in turn will change your actions.
00:05:34.760 This talk is about how you respond to failure. It’s something to be embraced—welcome it! Revel in it, even. Changing how you feel about failure will take time and effort; it won't happen overnight. However, the building of this skill will pay off when you see your progress speed up, as you're no longer held back by the fear of making a mistake.
00:06:07.320 Anyway, Git history can help you if you ever need it. You can always go back to where it was working before and begin the problem-solving process again with new information. Relax in the knowledge that you can't really break it beyond repair. It's safe to experiment; in fact, it's encouraged. Failing will help you and your code become more resilient.
00:06:37.740 Embracing a growth mindset in your skill development will set you up for success. I can’t remember exactly when, but somewhere in my teens, I decided I liked being wrong. Not only did I like being wrong, but it also became my new ethos. I liked being proven wrong because it gave me the chance to learn something.
00:07:03.740 I don't know what made me realize this, but at the end of it, after the embarrassment, I was smarter than I was before being wrong. If no one had proven me wrong, I would have just continued being wrong until someone or something helped me fix it. The embarrassment of being wrong diminishes with time, practice, and a different outlook.
00:07:39.600 If you want to know more about growth mindsets, definitely check out Carol Dweck's work. Speaking of famous people, this is a small list of celebrities, all of whom were not born into fame but made it happen for themselves despite countless failures. Except for Edison, he counted his failures. These are people who worked hard to achieve their levels of success; even Edison, who was notoriously litigious, could reframe failure as a learning experience.
00:08:50.400 However, it's ironic that while he could reframe failure, there's still such a stigma for us humans that he didn't want to admit it was happening. Now, here's the important caveat: you can do all the reframing you want, but if you don't learn anything from your mistakes, then you are wasting your time. To truly learn from your mistakes, you can't just sweep them under the rug; you need to sit with them for a while and be open about them.
00:09:25.380 Keeping that gained knowledge to yourself will hinder your growth from the experience. The hardest part of my job is admitting when I fail to find a solution and having to ask for help. I still struggle with my pride every time, and that's okay.
00:09:57.300 Being a work in progress is a shared experience. Even in last week's sprint, I hated admitting I was stuck on tickets and needed help. When I was a junior, it would take days for me to admit I needed help; I wanted so badly to prove that I could do my job. It was part of becoming a senior where I realized that my job was to fail fast, to venture out into the wilderness of what was possible and what wasn’t, and to fail as quickly as possible.
00:10:39.000 This way, we could move on to the next challenge. This is how progress is made—minds coming together to find a solution where there was previously only hypothesis and jumbled data. Getting used to failing and maintaining the grit to keep going are skills I developed over time.
00:11:19.440 It took me a long time to realize how much of a strength this was. It was actually when I was taken aside by that project manager I mentioned at the beginning of the talk, and he told me how much of an impact my sharing my failure made that I realized this was a skill I needed to hone.
00:11:56.420 Frequent and repeated failures are often where I learn the most. I like to use test-driven development (TDD) to help me understand what I'm trying to solve. I may not know what I need to do to fix it, but I know I can actively introduce failures. Starting from a place of failure gives me a freedom I wouldn’t have otherwise because it removes the risk from my experiments.
00:12:44.640 With TDD, I can just run my specs over and over again until the pieces start to come together. Now, to help you piece things together, I’ll hand it over to my colleague, Shayna Moore.
00:13:04.890 Okay, hello! Thank you, Kate, for the kind words. If we’re going to encourage you to fail fast, we’d like to provide you with some practical tips for how to handle error messages.
00:13:17.400 We know that error messages can be frustrating and stressful, especially for junior developers due to lack of experience, fear of failure, lack of confidence, and time pressure; some of the things that Kate has already mentioned. It might not help that many of the error messages you’ll see are red, which can trigger flashbacks to negative experiences like the one Kate just described.
00:13:45.300 But remember, they are red to stand out, to get your attention, and ultimately to help. Stop signs are red for the same reason. Could you imagine a world without them? My guess is it would be a lot more chaotic than usual, especially if you live in a city.
00:14:12.000 So instead of being afraid of these messages, let’s embrace them! Treat them as learning opportunities. I’ll cover nine ideas. The first seems kind of obvious, but it doesn't always happen: make sure you read and understand the error message. What is it trying to tell you? Sometimes, if you pay close enough attention, the solution lies within the error itself.
00:14:47.400 In this example, something went wrong when I called Shuffle on an array of fruits. The purple is the error type, the green is the error message, and the yellow is the Ruby interpreter offering a suggestion. So, I received a no method error: "Shuffle does not exist; did you mean Shuffle?" Yes, I did! It was a simple typo, which is really easy to miss.
00:15:20.760 Secondly, we want to identify the source of the error. One of my favorite parts of an error message is that they often come with a stack trace. A stack trace is a report displaying the sequence of function calls that led to the exception. They contain a lot of helpful information, like the file and the line number where the exception occurred.
00:15:49.140 In this Pig Latin converter program called Piggott, I received a no method error when I ran the program. The no method error said: "undefined method split for the number 42." Looking at this stack trace, I can see that the error occurred on line three of the Piggott file in a method called picket.
00:16:11.520 Using tips we'll discuss later, I learned that the method split is a Ruby method for strings, and it can’t be used on integers. If you can remember this example, we will revisit it. I intentionally raised an error just for demonstration purposes, resulting in a runtime error.
00:16:49.380 Looking back at the stack trace, we can see that method C was called by line six of method B, which in turn was called by line two of method A, and ultimately it was called on line 13 of the main program. Remember this example as well; we will see it again soon.
00:17:22.560 So far, all of my examples have been very simple and contrived. What do you do when your stack trace looks like this? Your reaction might be confusion. The best thing you can do is to slow down and read it carefully.
00:17:49.140 I received this error when I ran seeds in a Rails application. The task aborted due to a type error. Can you spot the offending line? It's here, and our heuristic to help you find it is to look for where the lines change from the bundled gems to where the lines start with 'app,' assuming the error comes from your application.
00:18:08.520 In this error, we can see it occurred in the decorate works type method on line 11 of the child indexer RB file, in a gem called triple if print that I had cloned to my vendor directory for local development. That's a lot of helpful information and such a time saver. When we say that error messages are friends, this is exactly what we need, and we should be grateful for them instead of scared.
00:18:53.880 I wanted to include this example because as a Rails developer, you'll likely see or have seen this error page a lot. In fact, Kate shared one earlier. As a junior Dev, I took this error page for granted and didn’t realize how jam-packed with helpful information it was. It’s also interactive.
00:19:11.880 Starting from the top, it tells you the error type and specifies the controller and action it came from. In this case, it indicates that this error occurred on line 11 in a partial called sidebar. The error message also includes a helpful "Did you mean?" statement.
00:19:49.680 The extracted source section highlights where the actual error occurred. I refer to this as context. Next, we have the trace templates, which in this example shows that the dashboard is responsible for rendering the sidebar partial. We can see the root of the application.
00:20:23.520 The exciting part, in my opinion, is that it's interactive. You can click on each link; it will unfold the stack trace and you can examine what was happening in your code at that particular point. You will see that I included an example for how this page looks if you have a routing error, which is also very helpful.
00:20:50.280 From there, you will be able to filter and search for all the available routes in your application. It includes the route helper, available HTTP verbs, the path, and the controller and actions responsible. To summarize, the error page is incredibly helpful, and I highly encourage you to play around with it the next time you see one.
00:21:30.960 For debugging tools, as Rails developers, we have several options. Some popular ones include Pry, Byebug, Web Console, and built-in debuggers. Debugging tools allow us to set breakpoints at specific points in our program, meaning the program will pause, and from there, you can execute your code line by line.
00:21:53.220 You can inspect variables and values along the way. Revisiting this Pig Latin program, remember that I got a no method error previously. We were able to follow the stack trace and identify that on line 25, I passed an integer instead of a string. Let's pretend I didn’t know this so we have an opportunity to use a debugger.
00:22:38.160 The first thing I’d do is set a breakpoint near the offending line, which I would identify from the stack trace, and then I would start my program. Personally, I would be interested in inspecting the parameter named 'str,' which usually stands for string. When I ask for its value, I get the number 42—definitely a clue that something's not right here. Next, I could run the line where I actually failed.
00:23:54.540 I could use the keyword 'next' for that, but instead, I use 'play l' and the line number to execute that line, which revealed the error we saw earlier. 'Play l' stands for 'play line' and is a Pry-specific tool that I use often. The point is to find a debugging tool you like, learn it well, and ensure that your debugging can be efficient.
00:24:47.520 Now, returning to our simple stack trace example, I’d like to share four of my favorite debugging methods.
00:25:06.960 The first method is 'caller,' which generates the stack trace report as we saw earlier. The stack trace example clearly reveals that method C was called by method B, which was in turn called by method A, and so on.
00:25:41.400 The next method, Source Location, was mentioned yesterday in a keynote, and I was excited because I use it often. It’s incredibly valuable; if you’re in a large application with lots of files, it can show you exactly where everything is defined. In this example, I called it on method C, and it revealed the file and line number where it was defined.
00:26:06.720 The next tool is Pry-specific, called 'source.' It’s similar to Source Location, but instead of showing where it is located, it returns the method definition itself. If I were to type puts and call 'source' on method A, it would return the contents of the method.
00:26:37.740 Lastly, there's 'backtrace.' This is useful when you’re rescuing exceptions and need to produce the stack trace for that particular error. Hopefully, you’re all still with me.
00:27:09.120 We are nearly halfway there. The next three points can be lumped under a common problems checklist, and I would argue that these will be the most frequent issues you encounter as a junior or new programmer. However, spoiler alert: many of the issues I face as a senior developer also trace back to these three points.
00:27:49.920 The first one isn't too bad because if you have a syntax error, your Ruby code won’t run. However, this can be frustrating because it’s easy to overlook. Has anyone ever stared at a problem, trying to figure out what’s wrong, only to realize you’re missing a comma?
00:28:10.920 To avoid this, use a good text editor or IDE (Integrated Development Environment), or a plugin that highlights your syntax errors as you type. In this example, I encountered an error when running a program due to a syntax error, which was actually quite helpful. But I didn’t need to get that far because I use Visual Studio Code.
00:28:46.620 It highlights my syntax errors as I type. In this case, I was missing a closing parenthesis, which it flagged with a red highlight. Once I fixed the problem, as shown in the bottom example, there are no more red highlights, and I can run the program successfully.
00:29:24.060 Common sources of errors also include incorrect inputs and outputs. For example, this add numbers program should return the sum of two arguments. However, when I ran it, it caused a type error saying a string can't be coerced into an integer. Looking at line seven, I passed two different data types: an integer and a string.
00:29:48.540 Every time you think you know what to expect, be aware of these possible pitfalls. Now, what if I need a logic mistake that impacts my code's output? In my add numbers method, I mistakenly wrote A minus B instead of A plus B. If I called it with five and five, I’d expect a return of 10, but it returned zero, causing a serious bug in my application.
00:30:14.580 Even if your code is free of syntax errors and runs without crashing, and your inputs look fine, you can still have logical errors leading to unexpected behaviors in your program. The Ruby interpreter will still execute it.
00:30:45.240 A common strategy to catch both logical and output errors early is to use TDD (Test Driven Development), which is something Kate mentioned earlier. In this practice, we write our tests first before any code.
00:31:11.580 This ensures our programs behave exactly as we expect. For example, I created a spec that expected the add numbers method to return 10 when called with five and five. I ran the spec and received an error, as I hadn’t written any logic at all. The next step would be to write the minimum amount of code needed for the spec to pass.
00:31:32.640 So I wrote A plus B in my code, re-ran the program, and it passed. With this type of workflow, I would have definitely caught the logical and output errors from before.
00:32:01.320 Now, if you encounter a particularly hard and confusing error message, this is the time to search for online resources for guidance. There are plenty of online forums, blogs, and documentation sites. Some popular choices include Stack Overflow and various documentation for languages, frameworks, and gems.
00:32:25.550 However, I would recommend avoiding the temptation to just copy and paste. Try to genuinely understand your code when you find a solution. Ask yourself if what you’re reading is relevant to your use case.
00:32:41.780 When reading documentation, ensure you're looking at the correct version. Oftentimes, the success of finding a solution will depend on how well you can Google.
00:33:07.440 Another thing you can try that is new and exciting is AI tools. I’ll preface this by saying I don’t have much experience with GitHub’s Copilot; I just gained access. Therefore, I’ll focus on ChatGPT.
00:33:24.840 Copilot is designed for developers and understands the context of your code, while ChatGPT is more general. I’m still learning the best ways to use it and ask questions.
00:33:43.560 In the previous example, I asked ChatGPT what the error meant: "Oh, it's a string; it can't be coerced into an integer." And when I asked, I received a helpful response that encouraged me to figure out what I needed to do.
00:34:09.540 ChatGPT could be a valuable tool for gaining guidance on various issues, but it’s important to mention some cautions.
00:34:27.720 First, don’t treat it as a source of truth; it can be wrong. Personally, I’m currently more comfortable asking it questions.
00:34:39.840 Exercise caution when copying and pasting your code into ChatGPT due to the terms of use which allows them to use your information to train AI models. You may have seen headlines about companies' data leaks due to employees using ChatGPT.
00:35:04.680 As a general rule of thumb, don’t input private or sensitive data. I highly recommend a session from Josh Puetz that covers best practices for programming fairly with AI.
00:35:27.720 Lastly, Eric Houston, a Twitch streamer and YouTuber, has fascinating content on using Copilot. We are almost done. You’ve tried all the things by now, but if you still don’t have a solution, I’d recommend stepping away from your computer to take a break.
00:36:03.840 When you reconnect and still feel stuck, be humble and ask for help. This is the time to share your error message with your Dev team. In our company, we created a Slack engineering channel for this purpose.
00:36:40.740 This channel has become a repository of questions from everyone on the team. Chances are someone may have already encountered the problem and can quickly jump in to help you.
00:37:03.510 In an example, I asked a question, and my great co-presenter, Kate, responded in the thread, offering to be a second pair of eyes. Often, that’s all you need.
00:37:25.440 But when you do find a solution, I recommend ending your question thread with ‘solved’ or a similar keyword. This gives others quick breadcrumbs to follow and saves a lot of time.
00:37:46.320 By documenting what you’ve encountered while it’s still fresh in your brain, the learning process sinks in deeper. That’s all I have for you today. Hopefully, we’ve empowered you with the right mindset and tools to create a troubleshooting framework that will help you embrace the failures and challenges you encounter as a developer.
00:38:09.480 In doing so, you will become more confident, skilled, and successful in your work. Your programs will become more robust and reliable, and your customers and team will be happier with the high-quality code and growth-minded attitudes you’ll contribute.
00:38:35.279 So, now we’ve got some time for Q&A. Does anyone have any questions?
00:38:40.919 What I would do first is repeat the question so everyone can hear it. The question is, if you're working with an older version of Rails and it isn't an updated code base, how do you find the documentation you need?
00:39:09.480 Well, I recommend going to the Rails Guides and finding the specific version of Rails you’re working with. Go through how things were built in that version.
00:39:30.660 Alternatively, if it’s not Rails but an old gem, I would visit GitHub to ensure you’re looking at the version of the code corresponding to your project. I can’t tell you how often I’ve looked at the wrong main branch.
00:39:50.160 The things have changed too much over time. Thus, check your versions and be sure you're reading documentation specific to your version. Searching for the specific version you're working with can lead you to what you need.
00:40:09.960 The next question is about mentoring—if you consider yourself a senior developer and want to help a junior developer but don’t want to hand them the answers, what should you do?
00:40:31.680 I would suggest that you hold your tongue. It is tough sometimes not to just share information. You want them to succeed quickly, but they will retain more if they uncover the answers themselves.
00:40:51.720 It’s important to equip them with the problem-solving skills to get there. What I usually do is walk through the problem-solving process with them, guiding them through their searches until they arrive at the solution themselves.
00:41:12.420 Sheila mentioned that it’s often more valuable than just giving them the answer outright. You’re there to guide, and often, you may not know precisely how to solve the problem, but having the skills to find the right answer is crucial.
00:41:32.160 Thank you again for attending our talk! We work for Soft Serve by scientist.com, and if you'd like to work with us, please feel free to reach out. Enjoy the conference!