Error Messages Decoded: What They Mean and How to Fix Them
Stack traces, cryptic errors, and mysterious crashes — learn to read error messages like a developer and fix them with Claude Code's help.
Why error messages exist and how to read them
Error messages are not punishment — they are your code trying to tell you what went wrong. Every error message contains three pieces of information: what happened, where it happened, and often why it happened. The problem is that error messages are written for developers, not humans. They use jargon, abbreviations, and assume you know the codebase. With Claude Code, you can paste any error message and get a plain English explanation. But understanding the structure yourself makes you faster and more independent. Create a practice project: mkdir error-practice && cd error-practice && npm init -y. Start Claude Code: claude. Ask it: Create a file called errors.js that deliberately contains five common JavaScript errors: a syntax error, a reference error, a type error, a range error, and an undefined property access. Put each in its own function so I can trigger them one at a time. Do not fix them — I want to see the error messages. Run the first one: node -e "require('./errors').syntaxError()". You will see something like: SyntaxError: Unexpected token } at errors.js:3:15. Read this as: the type of error is SyntaxError, the description is Unexpected token }, the file is errors.js, the line is 3, and the column is 15. The line number is the most important piece — it tells you exactly where to look. Ask Claude Code: Explain this error message to me in plain English and show me how to fix it. The explanation should be immediate and clear. Over time you will recognize patterns and skip the AI step entirely.
Stack traces: following the breadcrumbs
A stack trace shows you the chain of function calls that led to an error. It is like a trail of breadcrumbs from where the error occurred back to where the code started. Ask Claude Code: Create a file called stack-demo.js with four functions: main calls processUser, processUser calls validateEmail, validateEmail calls checkDomain, and checkDomain throws an error. Run it and show me the stack trace. Run it: node stack-demo.js. You will see something like: Error: Invalid domain at checkDomain (stack-demo.js:12:9) at validateEmail (stack-demo.js:8:3) at processUser (stack-demo.js:4:3) at main (stack-demo.js:1:3). Read the stack trace from top to bottom: the first line is where the error occurred (checkDomain at line 12). Each subsequent line shows what called the function above it. The trail goes checkDomain was called by validateEmail was called by processUser was called by main. The fix is usually in the first or second frame — that is where the actual problem lives. Frames deeper in the stack are just the path that led there. Ask Claude Code: Add try-catch blocks at different levels of the call chain. Show me how catching the error in validateEmail versus catching it in main changes what information is available and how the error is handled. Common stack trace confusion: lines referencing node_modules or internal Node.js files are framework code, not your code. Scan down the stack trace until you find a line in your own file — that is where to focus. If the entire stack trace is framework code, the error is in how you called the framework, not in the framework itself.
JavaScript and Node.js common errors
Certain errors appear so frequently that recognising them becomes second nature. Ask Claude Code: Create a file called common-errors.js that demonstrates each of these common errors with a function that triggers it and a comment explaining the fix. TypeError: Cannot read properties of undefined — the most common JavaScript error. It means you tried to access a property on something that is undefined. Usually caused by a missing variable, a typo in a property name, or data that has not loaded yet. Fix: check that the variable exists before accessing properties. ReferenceError: x is not defined — you used a variable that does not exist. Usually a typo or a missing import. Fix: check spelling and ensure the variable is declared. SyntaxError: Unexpected token — your code has a structural problem like a missing bracket, extra comma, or unclosed string. Fix: look at the line number and check for missing punctuation. TypeError: x is not a function — you tried to call something that is not a function. Usually means you imported wrong or the variable is not what you think. Fix: check the import and log the variable's type. ENOENT: no such file or directory — Node.js cannot find a file you referenced. Fix: check the file path and ensure the file exists. EADDRINUSE: address already in use — another process is using that port. Fix: kill the other process or use a different port. Run each function: node -e "require('./common-errors').undefinedProperty()". Read each error, then ask Claude Code to explain and fix it. After seeing these errors a few times, you will recognise them instantly.
npm and package errors
Package management errors are some of the most confusing because they involve dependency trees, version conflicts, and platform-specific issues. Ask Claude Code: Create a guide to the most common npm errors with examples and fixes. The errors to cover are: MODULE_NOT_FOUND, ERESOLVE unable to resolve dependency tree, peer dependency warnings, permission errors on global install, and node version compatibility errors. For MODULE_NOT_FOUND: this means Node.js cannot find a package you are importing. Run npm install to install dependencies. If it persists, delete node_modules and package-lock.json and run npm install again: rm -rf node_modules package-lock.json && npm install. This solves 90 percent of MODULE_NOT_FOUND issues. For ERESOLVE: two packages require different versions of the same dependency. Ask Claude Code: Show me what is conflicting and suggest a resolution. Options include updating the conflicting packages, using npm install --legacy-peer-deps (a temporary workaround), or finding compatible versions. For permission errors (EACCES) on macOS or Linux when running npm install -g: never use sudo with npm. Instead, configure npm to use a different directory: mkdir ~/.npm-global && npm config set prefix ~/.npm-global and add ~/.npm-global/bin to your PATH. For node version issues: install nvm (Node Version Manager) to switch between Node.js versions. Ask Claude Code: Check my current Node.js version and tell me if it is compatible with the packages in this project. Look at the engines field in package.json. If there is a mismatch, nvm install and nvm use will switch to the right version.
API and network errors
Network errors have their own vocabulary. Ask Claude Code: Create a file called network-errors.js that simulates or triggers each of these common network errors with a description and typical fix. Demonstrate: ECONNREFUSED, ETIMEDOUT, ENOTFOUND, HTTP 400 Bad Request, HTTP 401 Unauthorized, HTTP 403 Forbidden, HTTP 404 Not Found, HTTP 429 Too Many Requests, and HTTP 500 Internal Server Error. ECONNREFUSED means the server is not running or not accepting connections on that port. Check if the server is started and the port is correct. ETIMEDOUT means the request took too long — the server might be overloaded or unreachable. Add a timeout to your requests and retry logic. ENOTFOUND means DNS could not resolve the hostname — check your URL for typos and verify internet connectivity. HTTP status codes are grouped by category: 4xx means you made a mistake (bad request, wrong credentials, missing resource), 5xx means the server has a problem. For 400 errors, check your request body and headers. For 401, check your API key or token. For 403, you do not have permission — check your account's access level. For 404, the URL is wrong or the resource was deleted. For 429, you are sending too many requests — add delays between requests. For 500, the problem is on the server side — retry after a delay or contact the service provider. Ask Claude Code: Add retry logic to a fetch function that retries 3 times with exponential backoff for 429 and 5xx errors but does not retry 4xx errors since those require a fix, not a retry. This pattern is standard in production applications.
TypeScript errors explained
TypeScript errors catch bugs before your code runs, but they can be cryptic. Ask Claude Code: Create a file called ts-errors.ts that demonstrates the 8 most common TypeScript errors with examples and fixes. Include: Type X is not assignable to type Y, Property does not exist on type, Object is possibly undefined, Argument of type X is not assignable to parameter of type Y, Cannot find module, Type assertion errors, Generic type errors, and missing return type errors. The most common is Type X is not assignable to type Y. This means you are using a value where TypeScript expects a different type — like passing a string where a number is expected. Fix: check what type the function expects and convert your value. Property does not exist on type means you are accessing a property that TypeScript does not know about. This often happens with API responses typed as unknown or with missing interface definitions. Fix: define the type properly or use type assertions (carefully). Object is possibly undefined is TypeScript protecting you from the Cannot read properties of undefined error. It knows the value might be undefined and forces you to check first. Fix: add a null check (if (value !== undefined)) or use optional chaining (value?.property). Ask Claude Code: For each error, show me the wrong code, the error message, and the corrected code side by side. Explain in plain English what TypeScript is trying to protect me from. TypeScript errors feel annoying when you are learning, but each one represents a bug that would have crashed at runtime. The error at compile time is a gift — it is far easier to fix than a runtime crash in production.
Using Claude Code as your debugging partner
The most effective way to debug with Claude Code is to give it context, not just the error. Ask Claude Code: Create a file called debug-workflow.md that documents the optimal debugging workflow with Claude Code. Include example prompts for each step. The workflow has four steps. Step 1, share the error with context: instead of just pasting the error, tell Claude Code what you were trying to do. Bad prompt: TypeError: Cannot read properties of undefined reading map. Good prompt: I am trying to render a list of users from an API response. When the component loads, I get TypeError: Cannot read properties of undefined reading map. The fetch call is in useEffect and I am storing the result in a users state variable. Step 2, ask for diagnosis before fix: say Explain why this error is happening before suggesting a fix. This teaches you the underlying cause so you can prevent it next time. Step 3, request a fix with explanation: say Fix this error and explain what you changed and why. Review the fix before accepting it — understanding the fix is more valuable than the fix itself. Step 4, ask for prevention: say How do I prevent this type of error in the future? What patterns or practices would catch this earlier? Claude Code might suggest adding TypeScript types, writing tests, or adding defensive checks. Ask Claude Code: Create a script called error-logger.js that wraps any script and captures errors with full context — the error message, stack trace, the code around the error line, and the values of variables in scope. This creates a richer error report that makes debugging faster whether you use AI assistance or not. The goal is not to never see errors — that is impossible. The goal is to read them quickly, understand them deeply, and fix them confidently.
Building your personal error reference
After working through this guide, you have encountered dozens of error types. The most effective debugging habit is maintaining a personal error reference — a document where you record errors you have encountered, what caused them, and how you fixed them. Ask Claude Code: Create a file called error-reference.json with a structured format for recording errors. Each entry should have the error type, the full error message, what caused it, how to fix it, a code example showing the fix, and tags for searching. Populate it with every error type we covered in this guide. Then create a simple script called lookup.js that lets me search my error reference by keyword. Run it: node lookup.js "cannot read". It should find the TypeError: Cannot read properties of undefined entry and show the cause and fix. This is your personal Stack Overflow — built from errors you have actually encountered, with fixes you have actually verified. Ask Claude Code: Add a function to record new errors from the command line. I want to run node lookup.js --add, paste an error message, describe the cause and fix, and have it added to my reference automatically. Over time, your reference becomes a valuable knowledge base. Every error you encounter once and document is an error you fix in seconds the next time. This compounds: after a few months of recording errors, you will have a comprehensive reference covering every common error in your tech stack. Share it with your team — everyone benefits from collective debugging knowledge. The errors that seem impossible today will feel routine within weeks. That transformation from confusion to confidence is the real deliverable of this guide.
Debugging with AI
This guide is hands-on and practical. The full curriculum covers the conceptual foundations in depth with structured lessons and quizzes.
Go to lesson