Building Apps with AILesson 27 of 87

Contents

Building Apps with AI

Lesson 27 of 87. Sign in to keep your place.

Module 3 · Reading and checking what came back

Printing what you cannot see

8 min read

The oldest debugging tool still wins

When an app does something you cannot explain, the fastest route is almost never a debugger. It is printing the values at three points and looking at what actually arrived.

JavaScript
console.log('1 received:', body)
console.log('2 after validation:', parsed)
console.log('3 rows found:', existing.length)

Number your prints. When the output stops at 2, you have located the failure to a range of about ten lines without reading any of them, and that beats an hour of reasoning about what the code ought to do.

Where the output goes

This catches everybody once. A console.log in browser code appears in the browser console. A console.log in server code appears in the terminal running the server, or in your host’s log page in production. Same function, two different places, and looking in the wrong one produces the false conclusion that the code never ran.

If you are not sure which side a file runs on, print something distinctive and look in both.

Print the thing, not that you got there

JavaScript
console.log('here')                    // useless
console.log('slots', slots)            // better
console.log('slots', JSON.stringify(slots, null, 2))  // best for objects

Objects logged plainly can print as [Object] or, in some browsers, show their state at the moment you expand them rather than the moment they were logged, which is confusing when the value changed in between. Stringifying takes a snapshot.

And print the type when something is behaving oddly: typeof value distinguishes "30" from 30, which is the cause of a whole family of arithmetic bugs where prices add up as text.

Four values worth printing at any boundary

Whenever data crosses from one part of the system to another, print:

  • What arrived, before anything touches it.
  • The identity in play: which user the server believes is asking.
  • What the query returned, at least its length.
  • What is being sent back.

Most bugs are a mismatch at one of those four points, not an error inside a function.

Moving from prints to logs

console.log is for the next twenty minutes. For anything that will run in production, you want lines that are searchable and safe:

JavaScript
console.log(JSON.stringify({
  event: 'booking.rejected',
  reason: 'overlap',
  stylistId,
  startsAt,
  requestId,
}))

One line, structured, greppable. Every host’s log viewer can search text, so booking.rejected finds every occurrence across a week. A requestId generated at the start of each request and included everywhere lets you follow one user’s journey through interleaved output, which is the difference between logs you can use and logs you scroll past.

What must never be logged

This matters more than it sounds, because logs are stored, backed up, shared with your host, and sometimes readable by anybody with access to your dashboard.

Never log passwords, session tokens, API keys, full card numbers, one-time codes, or complete request bodies containing personal data. Log an id rather than a person.

A console.log(req.body) on a signup route writes your users’ passwords into your hosting provider’s log storage in plain text. This is not hypothetical; it is one of the more common ways small apps leak credentials, and it is always accidental.

Clean up, deliberately

Before committing, search for console.log and decide about each one. Some become real structured logs. The rest go.

Bash
grep -rn "console.log" --include="*.ts" --include="*.tsx" src app lib

Agents leave these behind constantly. They are noise, they slow things down slightly, and occasionally one of them is printing something it should not.

The debugger, briefly

Your editor can pause execution and let you inspect every variable at that moment. It is better than printing for a complicated bug, and it is worth an hour of your time eventually: in VS Code, a breakpoint is a click in the margin.

But do not let anybody tell you printing is unprofessional. Working programmers print values constantly, because for most problems it is faster, it works identically on your laptop and on a production server, and it leaves a record you can read afterwards.

Every lesson here is open. Your progress is recorded once you pass the Building with AI exam.

Check your understanding

A print statement added to a server route never appears anywhere. What is the most likely explanation?

Pick the one you would defend. Your answer stays private.

Next lesson · 8 minWhen the model breaks your app

Stuck on something?Ask Beatriz, your AI tutor

How to cite: Addaly (2026) ‘Printing what you cannot see’, in Building Apps with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-apps-with-ai/printing-what-you-cannot-see (Accessed: 13 October 2026).