Good error handling separates amateur code from production code. Here's how we handle errors at Google.
The Error Hierarchy
Error
├── TypeError // Wrong type operation
├── ReferenceError // Undefined variable
├── SyntaxError // Parse errors
├── RangeError // Value out of range
├── URIError // Bad URI functions
└── Custom errors // Your domain errorsCustom Error Classes
class AppError extends Error {
constructor(message, code, statusCode = 500) {
super(message);
this.name = "AppError";
this.code = code;
this.statusCode = statusCode;
Error.captureStackTrace?.(this, this.constructor);
}
}
class NotFoundError extends AppError {
constructor(resource) {
super(`${resource} not found`, "NOT_FOUND", 404);
}
}
class ValidationError extends AppError {
constructor(field, reason) {
super(`Validation failed: ${field} ${reason}`, "VALIDATION_ERROR", 400);
this.field = field;
}
}Async Error Handling
// Pattern 1: Go-style error returns
async function fetchUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new AppError("Fetch failed", "FETCH_ERROR", res.status);
return [await res.json(), null];
} catch (error) {
return [null, error];
}
}
const [user, error] = await fetchUser("123");
if (error) handleError(error);Global Error Boundaries
// Browser
window.addEventListener("error", (event) => {
reportToSentry(event.error);
});
window.addEventListener("unhandledrejection", (event) => {
reportToSentry(event.reason);
event.preventDefault(); // Prevent console error
});
// React Error Boundary
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
componentDidCatch(error, info) { reportToSentry(error, info); }
render() {
return this.state.hasError
? <FallbackUI onRetry={() => this.setState({ hasError: false })} />
: this.props.children;
}
}Production Tips
- Never swallow errors silently — always log or report
- Include context: user ID, request ID, timestamp
- Use error codes, not just messages (messages change, codes don't)
- Set up source maps for readable stack traces in production