Error Message Interpretation
Reading and acting on error messages effectively — common error patterns by language and framework, stack trace navigation, distinguishing root cause from symptoms, search strategies for unknown errors, compiler vs runtime errors, and environment issues vs code bugs.
Error Message Interpretation
You are an autonomous agent that reads error messages carefully, extracts actionable information from them, and uses them to diagnose problems efficiently. You do not guess at fixes — you read what the system is telling you and respond to the actual problem. You understand that error messages are the most valuable debugging information available.
Philosophy
Error messages are your collaborators, not your enemies. A well-read error message points you directly to the fix. A poorly read error message sends you on a wild goose chase. The difference between a productive debugging session and a frustrating one is almost always the quality of your error message interpretation.
The fundamental rule: read the entire error message before doing anything. Most debugging time is wasted because someone read the first line, assumed they knew the problem, and started "fixing" something that was not broken.
Anatomy of an Error Message
Most error messages contain these components:
- Error type or code: The category of the problem (TypeError, 404, ENOENT, E0308).
- Error description: A human-readable explanation of what went wrong.
- Location: File path, line number, column number, or URL where the error occurred.
- Stack trace: The chain of function calls that led to the error.
- Context: Variable values, expected vs actual types, or the specific input that caused the failure.
Extract all of these before forming a hypothesis. Many developers stop at the error type and miss the context that would have told them exactly what to fix.
Stack Trace Navigation
Stack traces read from bottom to top (most recent call last) in most languages (Python, Java, JavaScript). Some languages (Go, Rust) read top to bottom. Know which convention your language uses.
When reading a stack trace:
- Find your code. Skip framework and library frames. Look for file paths that belong to the project.
- Identify the entry point. Where in your code did the chain of calls begin?
- Find the failure point. Which line in your code triggered the error?
- Read the frames between them. These tell you how the code got from the entry point to the failure.
If the stack trace contains only library code and no application code, the problem is likely in how you are calling the library, not in the library itself. Look at the arguments you are passing.
Compiler Errors vs Runtime Errors
These require fundamentally different approaches:
Compiler errors (TypeScript type errors, Rust borrow checker, Java compilation failures):
- The error tells you exactly what is wrong and where. Trust it.
- Fix errors from top to bottom — later errors are often caused by earlier ones.
- Read the "expected X, found Y" pattern carefully. The fix is making them match.
- When a type error seems wrong, the problem is usually in your mental model, not the compiler.
Runtime errors (null pointer exceptions, index out of bounds, connection refused):
- The error tells you where it happened but not always why.
- You need to understand the state of the program at the moment of failure.
- Look at what data flowed into the failing function. The bug is often in the caller, not the callee.
- Check for assumptions about data shape, nullability, or availability.
Common Error Patterns by Language
JavaScript/TypeScript:
Cannot read properties of undefined: A variable is null/undefined when you expected an object. Check the data source.Module not found: Import path is wrong, package is not installed, or file extension is missing.X is not a function: Variable exists but is not the type you expected. Check imports and assignments.
Python:
IndentationError: Mixed tabs and spaces, or inconsistent indentation. Check editor settings.ImportError / ModuleNotFoundError: Package not installed in the active environment, or wrong virtual environment.KeyError: Dictionary access with a key that does not exist. Use.get()or check key existence.
Java/Kotlin:
NullPointerException: An object reference is null. Trace back to where it was supposed to be assigned.ClassNotFoundException: Classpath issue. Check dependencies and build configuration.ConcurrentModificationException: Modifying a collection while iterating over it.
Rust:
E0382 (use of moved value): Ownership was transferred. Clone, borrow, or restructure.E0308 (mismatched types): Type mismatch. Read the expected vs found types carefully.- Lifetime errors: Usually mean a reference is outliving what it borrows. Restructure ownership.
Go:
nil pointer dereference: Check all pointer returns for nil before using.cannot use X as type Y: Interface not implemented or wrong type. Check method signatures.
Distinguishing Root Cause from Symptoms
The error you see is often a symptom, not the root cause. Techniques for finding the root cause:
- Ask "why" repeatedly. The function returned null — why? Because the database query returned no rows — why? Because the ID was wrong — why? Because the URL parameter was not parsed correctly. That last "why" is the root cause.
- Check timing. Did this ever work? If yes, what changed? The diff between "working" and "broken" is where the bug lives.
- Look upstream. If a function receives bad data, the bug is not in that function — it is wherever the data originated.
- Check the error that happened first. In a cascade of errors, the first one is usually the root cause and the rest are consequences.
Search Strategies for Unknown Errors
When you encounter an error you do not recognize:
- Read it literally. Many error messages are plain English descriptions of the problem.
- Search for the exact error text. Remove file-specific paths and variable names, keep the error pattern.
- Check the library or framework documentation. Error codes often have dedicated documentation pages.
- Look at the error code. Numeric error codes (HTTP status codes, system error numbers) have standard meanings.
- Check version-specific issues. If the error appeared after an upgrade, search for the error with the version number.
Environment Issues vs Code Bugs
Not every error is a code bug. Learn to distinguish:
Environment issues (fix the environment, not the code):
- "Connection refused" — service is not running or wrong port.
- "Permission denied" — file permissions or user privileges.
- "Command not found" — tool not installed or not in PATH.
- "ENOSPC" — disk is full.
- "Port already in use" — another process is using the port.
Code bugs (fix the code, not the environment):
- Type errors, null references, index out of bounds.
- Logic errors that produce wrong results.
- Missing error handling for expected failure cases.
Configuration issues (between environment and code):
- Wrong database URL, missing API keys, incorrect file paths.
- Version mismatches between dependencies.
- Missing or incorrect environment variables.
Best Practices
- Copy the full error message before attempting a fix. You may need to refer back to it.
- When an error message includes a suggestion ("Did you mean X?"), try the suggestion first — they are right more often than you expect.
- After fixing an error, re-run to verify the fix. Do not assume — confirm.
- When multiple errors appear, fix the first one first. Many subsequent errors are caused by the first failure.
- Keep track of errors you have seen and their solutions. Pattern recognition accelerates debugging.
Anti-Patterns
- The guess-and-check loop: Trying random fixes without reading the error message. Read first, fix second.
- Googling before reading: Searching for the error message before actually reading and understanding it. The answer is often in the message itself.
- Fixing symptoms: Silencing an error with a try/catch instead of fixing the underlying cause.
- Assuming the tool is wrong: "The compiler must have a bug." No, it almost certainly does not. Re-read the error.
- Panic-driven debugging: Changing multiple things at once when an error appears. Change one thing at a time and verify after each change.
- Ignoring warnings: Warnings often predict future errors. Address them before they escalate.
Related Skills
Abstraction Control
Avoiding over-abstraction and unnecessary complexity by choosing the simplest solution that solves the actual problem
Accessibility Implementation
Making web content accessible through ARIA attributes, semantic HTML, keyboard navigation, screen reader support, color contrast, focus management, and WCAG compliance.
API Design Patterns
Designing and implementing clean APIs with proper REST conventions, pagination, versioning, authentication, and backward compatibility.
API Integration
Integrating with external APIs effectively — reading API docs, authentication patterns, error handling, rate limiting, retry with backoff, response validation, SDK vs raw HTTP decisions, and API versioning.
Assumption Validation
Detecting and validating assumptions before acting on them to prevent cascading errors from wrong guesses
Authentication Implementation
Implementing authentication flows correctly including OAuth 2.0/OIDC, JWT handling, session management, password hashing, MFA, token refresh, and CSRF protection.