How to read your app's logs to find the error

To find the error, go to the end of the log, scroll up to the first error line, and read the stack trace. The cause is usually in the message and the first line of your own code.

Updated 6 min read

Learning objectives

After reading this article you will be able to:

  • Tell normal output (stdout) from errors (stderr) and find the first error line
  • Read a Node.js stack trace and a Python traceback
  • Write useful logs and recognize the most common startup errors
On this page

When an app stops responding, the log is the first place to look. It is the process's diary: everything your code prints and everything the runtime complains about ends up there. Knowing how to read it saves hours of guessing.

The problem is rarely missing information; it's too much of it. A production log has hundreds of lines, and the useful error is one of them. To reach it, follow a fixed method in the same order every time.

AppstdoutstderrDashboard logsstdout + stderrError: connect ECONNREFUSEDat db.js:8:5TypeError: Cannot read ...exit code 11231Go to the end2Up to the 1st error3Your own code line
stdout and stderr reach the dashboard together: go to the end, scroll up to the first error line and find your own code line.

Where do log lines come from?#

Every process has two output streams. stdout carries normal output: console.log in Node.js, print in Python. stderr carries errors: console.error and the message the runtime prints when an exception is not handled.

In a terminal or a hosting dashboard, the two appear interleaved, in the order they arrived. That helps, because you see what the app was doing right before it failed.

In Node.js, an uncaught exception prints the stack trace to stderr and exits with code 1, according to the process documentation. An unhandled promise rejection (unhandledRejection) is, by default, raised as an uncaught exception. That is why an await without try/catch can take down your whole bot.

What is the method for finding the error?#

Here are the steps:

  1. Go to the end of the log. The last thing that happened is the current symptom.
  2. Scroll up to the first error line. Look for Error, Exception, Traceback, FATAL or ECONNREFUSED. Warnings (warn) are rarely the cause.
  3. Read the whole message. It gives the error type and, almost always, what was missing: a module, a variable, a port.
  4. Find the first line of your own code in the stack trace. Lines from node_modules or libraries show where the error passed through. The line with your file path shows where your code triggered it.
  5. Check what happened before. A database connection failure may have started 30 lines above the final error.

If the app restarts several times in a row, the log keeps each attempt, one after another. Compare the last one with the one before: the error that repeats is the one that matters.

How do you read a Node.js stack trace?#

Here is an example of an unhandled exception:

text
/home/app/index.js:12
  const name = user.profile.name;
                            ^

TypeError: Cannot read properties of undefined (reading 'name')
    at getName (/home/app/index.js:12:29)
    at handleMessage (/home/app/handlers/message.js:8:5)

Node.js v24.0.0

Read it top to bottom:

  • The line with ^ points at the exact spot in the code.
  • TypeError: ... is the type and message. Here, user.profile is undefined.
  • The at lines are the call stack, newest first. The first line with your project path (/home/app/index.js:12:29) gives file, line and column.
  • The last line shows the Node.js version, handy to confirm the runtime in use.

A Node stack trace shows where the error was created and extends to the start of synchronous execution, or to the frame limit set by Error.stackTraceLimit (see the errors documentation). In async code, some intermediate calls may not appear.

How do you read a Python traceback?#

Python uses the opposite order: the most recent call comes last.

text
Traceback (most recent call last):
  File "/home/app/main.py", line 20, in <module>
    start()
  File "/home/app/main.py", line 14, in start
    token = os.environ["TOKEN"]
  File "<frozen os>", line 714, in __getitem__
KeyError: 'TOKEN'

Start with the last line: KeyError: 'TOKEN' says the TOKEN environment variable does not exist. Then go up to find the line of your code that caused it (main.py, line 14). The header Traceback (most recent call last) tells you the newest call is at the bottom, as shown in the traceback module documentation.

When two exceptions are chained, Python prints During handling of the above exception, another exception occurred: between the blocks. The original cause is in the first block, and the error that finally propagated is in the last.

Which errors show up most when starting an app?#

Log message Likely cause What to do
Cannot find module 'x' / ModuleNotFoundError Dependency not installed or missing from package.json / requirements.txt Add the dependency and deploy again
KeyError or undefined on an environment variable Variable not set Set it and restart. See environment variables
EADDRINUSE Port already used by another process Use the right port or stop the other process
ECONNREFUSED Database or service down, wrong host or port Check host, port and that the service is up
JavaScript heap out of memory / MemoryError Not enough RAM Raise the RAM or reduce usage. See how much RAM and CPU
Invalid token / 401 Wrong or expired credential Generate a new one and update the variable

If the app crashes and comes back in a loop, the log shows the same error at every start. That is a restart loop caused by a fixed error, and automatic restart only repeats it. Read the guide on PM2 and auto-restart to understand this behavior.

How do you write logs that actually help?#

A good log answers "what, when and with which data" without exposing secrets.

  • Use levels. info for normal milestones, warn for what deserves attention, error for failures. That lets you filter.
  • Include context. failed to save user 4821: timeout beats error.
  • Log the whole error object, not just the message. Without the stack trace you lose the location of the failure.
  • Never print passwords, tokens or personal data. More people read a log than you think.
  • Write to stdout and stderr. That way you don't depend on a file path or rotation.

A minimal Node.js example:

js
process.on("unhandledRejection", (reason) => {
  console.error("unhandledRejection:", reason);
});

async function save(id) {
  try {
    await db.save(id);
    console.log(`user ${id} saved`);
  } catch (error) {
    console.error(`failed to save user ${id}`, error);
  }
}

In Python, the standard library's logging module does the same, and logging.exception("message") already includes the traceback.

How to do this on Square Cloud#

On Square Cloud, your app's logs appear in real time in the dashboard, the CLI, the VS Code extension and the mobile app. You apply the same method and follow a deploy or an error without opening a terminal on any server.

Apps run in isolated containers. Automatic restart is optional and comes on when you deploy from the dashboard: it brings the app back when the process exits with an error. Logs from before a restart stay visible, so after an unexpected restart, scroll up the log to find the error that caused it. Running out of memory is different: the app stops and only comes back when you raise its RAM and start it again.

When you change an environment variable, the change takes effect on the next restart, with no rebuild: restart and reread the log to confirm. Cubic, the AI agent in the dashboard, also reads logs to diagnose failures, always at your request. CPU, RAM and network metrics are recorded every 5 minutes and kept for 24 hours, which helps you match a memory error with real usage.

See the logs and metrics features in the platform features.

Deploy

Push from GitHub, the CLI or a ZIP and go live in seconds

Learn more

FAQs

Why does the log show an error while the app keeps running?

Not every error stops the process. An error caught by try/catch and only printed does not end the app. An uncaught exception does end the process, and an automatic restart can bring it back, so it looks like it never went down.

What is the difference between stdout and stderr?

They are two output streams of a process. console.log and print write to stdout. console.error and uncaught exception messages go to stderr. In a dashboard the two usually appear together, in the order they arrive.

The log shows only one line of the error. Where is the rest?

Check whether the dashboard limits the visible lines and scroll up. An exception spans several lines, and the real cause may be on the first line of the stack trace or in a chained block, such as 'During handling of the above exception' in Python.

Can I write logs to a file?

You can, but it is usually better to write to stdout and stderr and let the platform collect them. If you write to a file, cap its size and rotate it, or the disk fills up.

Next articleContainers vs virtual machinesContainers and virtual machines isolate apps differently: a container shares the host kernel, a VM brings its own. See how they compare and when to use each one.

More in Deploy

See all 33 articles