glimfly
guide updated

How do I read an error message without panicking?

The short answer

Every error has three parts: what broke (the first line), where it broke (a file and a line number you can open), and the trail that led there (the stack of calls beneath). You don’t read all of it. You read the first line, then scan down to the first file with a name you recognize as yours, and you ignore the library frames. Errors live in four places, depending on what failed: the browser console for frontend crashes, your terminal for build and startup failures, the Network tab for bad requests, and your host’s logs for anything that broke on the server. When you hand an error to your agent, paste the exact text instead of a screenshot, and say what you did right before it appeared. When there are twenty errors, fix the first one, because the rest are usually its echoes. And when the same error keeps coming back after three rounds with your agent, stop, revert to the last version that worked, and change one thing at a time from there.

The four places an error hides, and which kind lives where

An error only helps you if you’re looking where it landed. There are four places, and each one catches a different kind of failure.

The browser console catches frontend crashes: the red text that appears when the JavaScript running inside the page throws. This is where undefined errors and hydration mismatches show up. Open it with the keyboard: on macOS, Command+Option+J; on Windows and Linux, Control+Shift+J. (Command+Option+I, or F12 on Windows and Linux, opens the full DevTools, then you click the Console tab.) The browser console is the first place to look when a page loads blank or a button does nothing.

The terminal catches build and startup failures: the messages that scroll past where you (or your agent) ran npm run dev. A server that won’t start, a package that won’t import, a type error that halts the build, all of it lands here and never reaches the browser. If your app never even loaded, read the terminal first.

The Network tab catches bad requests. When the console says something vague like “Failed to fetch,” the Network tab in DevTools shows the actual request: which URL you called, and what came back. A red 404 or 500 in that list tells you far more than the console’s shrug. There’s no single hotkey for it, so open DevTools (F12, or Command+Option+I on Mac) and click Network, or open the Command Menu (Control+Shift+P, Command+Shift+P on Mac) and type “Network.” Whatever status code you find there maps straight to a meaning, which is what HTTP status codes are for.

Your host’s logs catch what broke on the server, in production, where your browser can’t see it. A serverless function that throws on Vercel or Netlify never prints to your console; it prints to the host’s log tab. When the browser shows a 500 but the console has nothing useful, the real error is usually waiting in those logs. (Our guide on why localhost works but production breaks walks through that whole gap.)

Anatomy of one stack trace, read top to bottom

Here’s a trace like one you’ll meet on an early React app. You clicked into a profile page, the screen went white, and this is what the console showed:

Uncaught TypeError: Cannot read properties of undefined (reading 'name')
    at UserCard (UserCard.jsx:12:22)
    at Profile (Profile.jsx:34:7)
    at renderWithHooks (react-dom-client.development.js:5529:26)
    at updateFunctionComponent (react-dom-client.development.js:8897:19)
    at beginWork (react-dom-client.development.js:10522:18)

It looks like a wall, but it breaks down into three parts.

Line one is what broke. TypeError means you used a value as the wrong type. Cannot read properties of undefined (reading 'name') means you tried to read .name on something that turned out to be undefined. In plain terms: you expected an object with a name on it, and you got nothing. That’s a classic undefined and null miss, usually data that hasn’t arrived yet.

Line two is where it broke. at UserCard (UserCard.jsx:12:22) points at your file, UserCard.jsx, line 12, column 22, inside the function called UserCard. This is the first name you recognize, because you wrote it. Open that file, go to line 12, and you’ll find something like user.name where user is undefined. Start every trace right here: the first frame that names a file of yours.

The lines below are the trail. at Profile (Profile.jsx:34:7) says UserCard was rendered by your Profile component, on line 34. That’s a lead, not noise: the empty user was probably handed down from Profile, so line 34 is where to check what you passed into UserCard. Everything after that, the react-dom-client frames, is library code. You didn’t write it, you won’t fix it there, and you can ignore it. The whole skill is reading down until the names stop being yours, then stopping.

The trace is printed newest-first. The line at the top is the last thing that ran before the crash, and each line below it is what called the line above. So “top to bottom” reads backward through time, from the moment of failure toward where the chain began.

The greatest hits, and what each one is actually saying

Most errors you’ll hit are one of a handful, wearing different words. Here’s the map from the text to the meaning.

What you seeWhat it’s telling youGo deeper
Cannot read properties of undefined (reading 'name')You reached for a property on a value that’s undefined or null, often data that hasn’t loaded, or a typo in its shape.undefined and null
x is not a functionSame family: you called something that isn’t a function, usually a bad import or a mistyped method name.import and export
Cannot find module 'react-router' or Module not foundA file or package your code imports isn’t where the import points, often an uninstalled package or a wrong path.import and export
EADDRINUSE: address already in use :::3000The port your dev server wants is already taken by another process, usually a server you never shut down.what is a port
blocked by CORS policy: No 'Access-Control-Allow-Origin' headerThe browser refused a cross-origin request because the server didn’t say it was allowed.CORS
Failed to load resource: 404 versus 500404 means the address you asked for doesn’t exist. 500 means the server crashed while handling a request it did receive.HTTP status codes
Hydration failed or Text content does not match server-rendered HTMLThe server’s HTML and the browser’s first render disagreed, often from a date, a random value, or window used while rendering.hydration error

Two habits make this table pay off. Read the exact words, because undefined, null, and not a function are different clues pointing at different fixes. And when a status code is involved, hold onto the split that trips up beginners most: a 404 versus a 500 is the difference between “the thing you asked for isn’t there” (usually your URL or your route) and “the server broke trying to give it to you” (usually your backend code, and the details live in your host’s logs, not the browser).

How to hand an error to your agent so it actually helps

Three things turn a blind paste into a fix.

Verbatim text beats a screenshot. Select the error in the console or the terminal and copy the actual characters, including the file name and the line number. A screenshot can crop the first line, blur a variable name, and forces the agent to read pixels instead of text, which is exactly when it starts to guess. Copy the words.

Say what you did right before it appeared. “I clicked Save and got this,” or “it happened the moment the page loaded,” tells the agent which path through your code ran. Without the trigger, the agent has to imagine one, and an imagined trigger leads to an imagined fix. This is also your best defense against AI hallucination: when you name the action and the error together, you can tell whether the fix your agent proposes actually touches the line that failed, or just sounds plausible.

When there are twenty errors, the first one wins. Errors cascade. One root failure throws, and everything that depended on it throws too, so a single missing value can flood your console with red. The first error in time is almost always the cause, and the rest are echoes of it. In the browser console, scroll up to the earliest red line. In a build log, read from the top down. Fix that one, re-run, and watch how many of the others disappear without you touching them.

When to stop the loop and revert instead

There’s a failure mode every vibe coder meets. You paste the error, the agent edits a file, a new error appears, you paste that one, and an hour later you’re further from working than when you started. The agent isn’t reasoning toward a fix anymore. It’s guessing, and each guess is built on the last broken guess.

Set the limit before you’re inside it. If you’ve handed the agent the same error three times and its edits aren’t converging (each change spawns a fresh error, or it keeps rewriting the same file two different ways), stop. Every extra round costs credits and quietly stacks up technical debt in code you understand a little less each pass.

The move is to revert to the last version that actually worked, then start over on purpose: reproduce the error once, read the first line and the first file you recognize with your own eyes, and change one thing. A looping agent is often a hallucinating one, inventing an API that was never real or a config option that doesn’t exist. Reading the error yourself is what lets you catch that, and it’s the rare skill that gets cheaper every single time you use it.

What Glim would tell you

Glimfly is building Glim, a firefly that sits beside your coding agent and says, in plain language, what just changed and what the last error actually meant. Reading errors is the habit Glim exists to make automatic: instead of pasting a red wall and hoping, you’d see the first line translated and the first file of yours pointed to, while it’s still one error and not twenty. So the next time the screen goes red, resist the paste for ten seconds. Read the first line, find the first file with your name on it, and tell your agent both the error and what you were doing. Every term in this guide has a plain-language entry in the dictionary for when a message moves faster than you can follow. And if you’d like Glim reading the terminal alongside you on your next build, the waitlist is open.

People also ask

“My agent keeps looping on the same error. What do I do?”

Stop pasting. After three rounds where the fixes aren't converging, the agent is guessing on top of its last guess. Revert to the last version that actually worked, then reproduce the error once and read it yourself: the first line tells you what broke, and the first file with your name on it tells you where. Hand the agent that plus what you did right before it happened, and change one thing at a time from there.

“Should I send my agent a screenshot of the error or the text?”

Text, copied verbatim. A screenshot can crop the important first line, blur a variable name, and forces the agent to read pixels, which is when it starts inventing fixes. Select the error in the console or terminal, copy the actual characters including the file name and line number, and paste that. Then add one sentence about what you clicked or loaded right before it appeared.

“There are twenty errors in my console. Which one do I fix?”

The first one. Errors cascade: one root failure throws, and everything that depended on it throws too, so a single missing value can fill the screen with red. The earliest error in time is almost always the real cause, and the rest are echoes. Scroll up to the first red line in the console, or read a build log from the top, fix that one, then re-run and watch how many others vanish on their own.

Words from this guide

web

Where is the browser console and what does it show?

The browser console is a panel built into every browser's developer tools that prints every error, warning, and logged message your page's JavaScript produces, in plain text you can copy and hand to your AI.

web

What do HTTP status codes like 404 and 500 mean?

An HTTP status code is the three-digit number a server sends back with each response, telling you in one glance whether the request worked, got redirected, or whose fault it was if it failed.

code

What's the difference between undefined and null?

undefined means a variable, property, or argument was never given a value, while null means something was deliberately set to empty, and JavaScript throws a TypeError the moment your code tries to read a property or call a method on either one.

code

What does "Module not found: Can't resolve" mean?

Import and export are the JavaScript keywords that let one file hand off a function, variable, or component to another file, and a mismatched path or export style is exactly what "Module not found" and "Cannot find module" errors are reporting.

web

What is a port, and why won't my server start on 3000?

A port is a number from 0 to 65535 that tells a computer which program on it should receive a piece of network traffic, so only one program can listen on a given port at a time.

code

What is a hydration error in a Next.js or React app?

A hydration error is React's warning that the interactive version it just built in the browser doesn't match the plain HTML the server sent down, usually because some value rendered differently on each side.

ai

What is an AI hallucination in code? When your agent invents things

An AI hallucination in code is when your agent confidently writes a function, library, or setting that simply doesn't exist.

free tool · no signup

See this in your own project Glim reads it in plain words.

Paste what your agent just did, a git diff, your terminal, or its summary, and Glim tells you what changed and what to check before you ship. Nothing stored.

Explain my session →