JavaScript console errors are bugs your code shipped with. Unlike syntax errors that prevent execution, runtime errors fire during execution — usually on specific user paths you didn't test. TypeError accessing undefined, ReferenceError for missing variables, unhandled promise rejections, third-party script failures. Each class has a systematic fix. This guide walks through diagnosis, the common patterns, and the error monitoring that catches new bugs before users complain.
The most common runtime error. Code tries to access a property on a value that's undefined or null.
// Bug: user.profile may not exist
function showName(user) {
return user.profile.name; // TypeError if no profile
}
// Fix 1: Optional chaining
function showName(user) {
return user?.profile?.name; // returns undefined gracefully
}
// Fix 2: Default with nullish coalescing
function showName(user) {
return user?.profile?.name ?? 'Anonymous';
}
// Fix 3: Explicit guard
function showName(user) {
if (!user || !user.profile) return 'Anonymous';
return user.profile.name;
}
Optional chaining (?.) is the cleanest modern fix. Supported in all modern browsers; transpiled by Babel for older targets.
Code references a variable that doesn't exist. Causes: typo, missing import, used before declared, removed code that left dangling references.
// Bug: missing import
function process() {
return moment().format(); // ReferenceError if moment not imported
}
// Fix: import the dependency
import moment from 'moment';
function process() {
return moment().format();
}
// Bug: typo
const userName = 'jane';
console.log(usrName); // ReferenceError - typo
// Fix: ESLint catches these at build time
const userName = 'jane';
console.log(userName);
ESLint with no-undef rule catches most ReferenceErrors at build time.
Async code that throws but isn't caught.
// Bug: no error handling
async function loadUser(id) {
const res = await fetch(`/api/users/${id}`);
return res.json(); // rejects on network failure
}
loadUser(1); // unhandled rejection if fetch fails
// Fix: handle the rejection
async function loadUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
} catch (err) {
console.error('Failed to load user', err);
return null; // or appropriate fallback
}
}
Global handler as a safety net (still need per-call handling for graceful UX):
window.addEventListener('unhandledrejection', (event) => {
Sentry.captureException(event.reason);
});
Third-party scripts (analytics, chat widgets, A/B test tools) often throw errors you didn't write. They pollute monitoring and can break the page.
// Wrap third-party initialisation
try {
window.someThirdParty.init({ key: 'X' });
} catch (err) {
console.warn('Third party init failed', err);
}
Sentry configuration to exclude noisy third-party errors:
Sentry.init({
dsn: '...',
beforeSend(event) {
// Ignore errors from third-party scripts
if (event.exception?.values?.[0]?.stacktrace?.frames?.some(
f => f.filename?.includes('third-party-domain.com')
)) {
return null;
}
return event;
}
});
For third-party scripts, SRI ensures the file you got matches what you expected. If the third party serves broken JS, SRI fails the script gracefully instead of executing broken code.
Async code that depends on order being a certain way, but isn't.
// Bug: component unmounted before async completes
async function loadAndSet() {
const data = await fetch('/api/data');
setState(data); // setState on unmounted component
}
// Fix: signal abort or component-aware
function MyComponent() {
useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(setState)
.catch(err => {
if (err.name !== 'AbortError') console.error(err);
});
return () => controller.abort();
}, []);
}
// Sentry quick setup
npm install --save @sentry/browser
// At app entry
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: 'YOUR_DSN_HERE',
environment: process.env.NODE_ENV,
release: process.env.GIT_SHA,
// Optional: session replay for context
integrations: [new Sentry.Replay()],
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});
Sentry's free tier handles small-medium sites. Alternatives: LogRocket (session replay focus), Datadog (full observability), Bugsnag (error focus).