JavaScript · Error Handling

Error Handling Interview Questions
With Answers & Code Examples

3 carefully curated Error Handling interview questions with working code examples and real interview gotchas.

Practice Interactively →← All Categories
3 questions0 beginner3 core0 advanced
Q1Core

How do you handle errors in async/await properly?

💡 Hint: try/catch, re-throw unexpected errors, never swallow silently
// Option 1: try/catch (most common)
async function fetchData() {
  try {
    const data = await api.get('/users');
    return data;
  } catch (err) {
    if (err.status === 404) handleNotFound();
    else throw err; // re-throw unexpected errors
  }
}

// Option 2: .catch() at call site
const data = await fetchData().catch(err => null);

// Option 3: go/to helper
const to = p => p.then(d => [null, d]).catch(e => [e, null]);
const [err, data2] = await to(fetchData());
💡 Always handle promise rejections — unhandled ones crash Node.js.
Practice this question →
Q2Core

How do you create custom Error types in JavaScript?

💡 Hint: Extend Error class — set this.name, call super(message); enables instanceof checks
class ValidationError extends Error {
  constructor(message, field) {
    super(message);                    // sets .message and .stack
    this.name = 'ValidationError';     // override — default is 'Error'
    this.field = field;                // custom property
  }
}

class NetworkError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.name = 'NetworkError';
    this.statusCode = statusCode;
  }
}

// Usage — instanceof lets you catch specific types
function validate(user) {
  if (!user.name)  throw new ValidationError('Name required',  'name');
  if (!user.email) throw new ValidationError('Email required', 'email');
}

try {
  validate({ name: '' });
} catch (err) {
  if (err instanceof ValidationError) {
    console.log(`Field "${err.field}": ${err.message}`);
  } else if (err instanceof NetworkError) {
    console.log(`HTTP ${err.statusCode}: ${err.message}`);
  } else {
    throw err; // re-throw unknown errors — don't swallow them
  }
}
💡 Always call super(message) — this sets .message and .stack correctly. Always set this.name — otherwise err.name shows 'Error' not 'ValidationError'.
Practice this question →
Q3Core

What is error propagation and when should you re-throw an error?

💡 Hint: Catch what you can handle; re-throw everything else; never silently swallow errors

Error propagation means letting errors bubble up the call stack until something can meaningfully handle them.

// ❌ Anti-pattern: silently swallowing errors
try {
  await doSomething();
} catch (err) {} // hides all bugs — never do this!

// ❌ Anti-pattern: catching all errors at every level
async function fetchUser(id) {
  try { return await fetch(...); }
  catch (err) {
    console.log('error!'); // useless — caller doesn't know what happened
  }
}

// ✅ Correct pattern: handle what you can, re-throw the rest
async function fetchUser(id) {
  try {
    const res = await fetch(`/api/users/${id}`);
    if (!res.ok) throw new NetworkError('Not found', res.status);
    return await res.json();
  } catch (err) {
    if (err instanceof NetworkError && err.statusCode === 404) {
      return null; // 404 is expected — handle it
    }
    throw err; // unexpected error — propagate up
  }
}

// ✅ Top-level handler
async function main() {
  try {
    const user = await fetchUser(1);
    render(user);
  } catch (err) {
    logToErrorService(err); // catch everything remaining
    showErrorMessage();
  }
}
💡 Rule: only catch what you can meaningfully recover from. If you can't handle it, re-throw. Handle everything else at the top of your app boundary.
Practice this question →

Other JavaScript Interview Topics

Core JSFunctionsAsync JSObjectsArrays'this' KeywordModern JSPerformanceDOM & EventsBrowser APIs

Ready to practice Error Handling?

Get AI feedback on your answers, predict code output, and fix real bugs.

Start Free Practice →