← All Articles 🌐 Live Website Analysis High By Nishant Kumar Verma Updated

Console Errors in Production: Runtime JavaScript Failures in AI-Built Apps

How to find JavaScript console errors on your live site with DevTools, a check after each deploy and error monitoring, plus the common errors in AI-built apps.

WEB-001 WEB-002

Quick Answer

Console errors in production are JavaScript exceptions and failed requests that happen in your users' browsers, where you never see them. To find them, open your live site with DevTools open (F12, then Console), load it in a headless browser after each deploy and fail the build on any error, and add an error monitoring tool such as Sentry for the errors that only happen with real users and real data.

The Visibility Problem: Errors You Never See

In production nobody watches the browser console except your users. An Uncaught TypeError or a failed API call breaks a page for them, and unless something reports it, you find out when someone emails you or simply leaves.

AI-built apps are especially prone to this. Bolt, Lovable, Cursor and v0 build against a preview that has the data and settings the code expects. Production has missing environment variables, empty tables and API responses with null where the code assumed an object, and code without error handling breaks on exactly those.

The Most Common Console Errors in AI-Built Apps

Error type Typical message Common cause in AI code
TypeError Cannot read properties of undefined (reading 'map') An API response assumed to be an array came back as null or an object
ReferenceError process is not defined A server-side environment variable read in browser code
Failed fetch Failed to load resource: net::ERR_CONNECTION_REFUSED A hardcoded localhost URL shipped to production
CORS error Access to fetch ... has been blocked by CORS policy The API does not allow requests from your production domain
Unhandled promise rejection Uncaught (in promise) TypeError: ... An await or .then() with no try/catch or .catch()
404 on a script GET /assets/index-abc123.js 404 A stale cached page asking for a file a newer deploy removed
Hydration error Hydration failed because the server rendered HTML didn't match the client. Next.js rendering dates, random values or window during the first render

The hydration message above is React 19's. React 18 apps show Expected server HTML to contain a matching ... for the same problem.

What AI-Generated Error Handling Often Looks Like

A data-fetching component like this works in a preview with seeded data and breaks in production when the API answers with an unexpected shape:

// BAD: no error handling, assumes the response shape
export default function UserDashboard() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('/api/user/profile')
      .then(res => res.json())
      .then(data => setData(data));
    // no .catch(): a failed request becomes an unhandled rejection
  }, []);

  return (
    <div>
      {/* crashes while data is null, or if posts is missing */}
      <h1>{data.user.name}</h1>
      {data.posts.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  );
}

If the API returns { "error": "unauthorized" }, data.user is undefined and the render throws Cannot read properties of undefined. Without an error boundary, React unmounts the whole tree and the user sees a blank page.

How to Fix It

// GOOD: checks the response, handles loading and errors
export default function UserDashboard() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('/api/user/profile')
      .then(res => {
        if (!res.ok) throw new Error(`API error: ${res.status}`);
        return res.json();
      })
      .then(setData)
      .catch(err => setError(err.message))
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Failed to load your profile. Please refresh.</div>;
  if (!data?.user) return <div>Profile not found.</div>;

  return (
    <div>
      <h1>{data.user.name}</h1>
      {(data.posts ?? []).map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  );
}

Four habits do most of the work: check res.ok before parsing, catch errors and show them instead of letting them escape, use optional chaining (data?.user) before reading nested values, and give arrays a fallback (data.posts ?? []) before calling .map().

How to Find Console Errors on Your Live Site

1. Look once, by hand

Open your site in Chrome, press F12, choose the Console tab and reload. Red entries are errors. Then open the Network tab and filter by status to see failed requests. Do this on every page that matters, signed out and signed in.

2. Check after every deploy, automatically

A headless browser can load your key pages and fail the deploy if anything logs an error. This short Playwright script catches errors logged with console.error and uncaught exceptions:

// console-smoke.mjs  (npm install --save-dev playwright, then npx playwright install chromium)
import { chromium } from 'playwright';

const SITE_URL = process.env.SITE_URL ?? 'http://localhost:3000';
const PAGES = ['/', '/pricing', '/login'];

const browser = await chromium.launch();
const page = await browser.newPage();
const errors = [];
page.on('console', (msg) => { if (msg.type() === 'error') errors.push(`${page.url()}: ${msg.text()}`); });
page.on('pageerror', (err) => errors.push(`${page.url()}: ${err.message}`));

for (const path of PAGES) await page.goto(new URL(path, SITE_URL).href, { waitUntil: 'networkidle' });
await browser.close();

if (errors.length) { console.error(errors.join('\n')); process.exit(1); }
console.log('No console errors');

Run it with SITE_URL=https://your-site.com node console-smoke.mjs after each deploy. A non-zero exit code fails the CI step. VibeDoctor's Vibe Check runs the same kind of check on every website scan: it loads your site's URL in a real browser and reports each console error, with the script that threw it.

3. Catch what only real users hit

Some errors only happen with a particular account, browser or sequence of clicks. Error monitoring tools such as Sentry, LogRocket and Datadog RUM send every unhandled exception from real browsers to a dashboard, with the stack trace and the steps that led to it. For a Next.js app, Sentry's wizard sets it up:

npx @sentry/wizard@latest -i nextjs

The wizard creates instrumentation-client.ts, which starts Sentry in the browser. Older guides use sentry.client.config.ts for the same thing.

Broken Links and 404s

The same scan covers a related failure: links and resources that return 404. In AI-built apps this usually happens when:

  • The AI generated links to routes that were never built
  • Image paths differ between your machine and the deployment
  • An API route was renamed but the fetch calls were not
  • A dynamic import path has a typo that only fires on one interaction

Broken links also cost you search traffic. Google's documentation says it does not index URLs that return a 4xx status, and removes already-indexed URLs that start returning one. A page reached only through a broken link drops out of search.

Find Them Before Your Users Do

Use three layers. Static checks catch obvious patterns before you deploy: ESLint with eslint-plugin-react-hooks, and TypeScript strict mode, which turns most "Cannot read properties of undefined" crashes into compile errors. A post-deploy browser check catches errors that fire on page load. Error monitoring catches the rest.

FAQ

How do I see JavaScript errors on my live site right now?

Open the site in Chrome, press F12, choose the Console tab and reload the page. Errors appear in red. Then check the Network tab for failed requests. Repeat on every important page, both signed out and signed in.

How do I check for console errors automatically after each deploy?

Load your key pages in a headless browser such as Playwright, listen for console messages of type error and for pageerror events, and exit with a failure if any appear. Run the script as a CI step after the deploy finishes.

Is it bad to leave console.log statements in production?

Yes. Leftover console.log calls can show user emails, API responses and internal state to anyone who opens DevTools. Remove them, or use an ESLint rule or a build step that strips them from production bundles.

Why does my AI-built app work in the preview but break in production?

The preview has the data, settings and environment the code was written against. Production has your real database, your real environment variables and real user input. Any assumption about data shape or a variable being set that held in the preview can fail in production.

What is a hydration error in Next.js and how do I fix it?

It happens when the HTML rendered on the server differs from what React renders in the browser. React 19 reports it as "Hydration failed because the server rendered HTML didn't match the client." Common causes are dates, random values and browser-only APIs such as window or localStorage used during the first render. Move that code into useEffect, or load the component with dynamic and ssr: false.

Diagnose your codebase - free

VibeDoctor checks for WEB-001, WEB-002 and 148 other issues across 21 diagnostic areas - security, performance, code quality, and more.

SCAN MY APP →