mcpField
E
error-handling

error-handling

github.com/metarhiaDevelopment6038 installsUpdated 12w ago
Repository

About error-handling

An error-handling skill for developers, covering JavaScript sync and async errors, layer boundaries, recovery, propagation, and process shutdown.

Key features

  1. 01Distinguishes programming and operational errors
  2. 02Handles sync and async exceptions
  3. 03Uses DomainError for business errors
  4. 04Provides retries and process-level handlers
  5. 05Covers graceful shutdown

Use cases

  1. 01Map API business errors to structured codes
  2. 02Retry transient network failures
  3. 03Investigate uncaught exceptions and rejections

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/metarhia/metaskills --skill error-handling

After installing, type/error-handlingin Claude Code to confirm it loaded.

Details

From the project README

Error Handling

Error classification

  • Programming errors: Bugs (TypeError, ReferenceError, assertion failures, etc.). Fix the code; do not catch and continue
  • Operational errors: Expected failures (network timeout, file not found, invalid input, etc.). Handle gracefully with recovery, escalation, user notification, or logging

Sync error handling

try {
  const result = parse(input);
  return result;
} catch (error) {
  console.error({ error });
  return defaultValue;
}

Async error handling

try {
  const data = await fetchData(url);
  return data;
} catch (error) {
  if (error.code === 'ECONNREFUSED') return fallback();
  throw err;
}

DomainError

Structured business errors with codes for the API layer:

({
  method: async ({ email }) => {
    const user = await domain.user.findByEmail(email);
    if (!user) return new DomainError('ENOTFOUND');
    return user;
  },
  errors: { ENOTFOUND: 'User not found' },
});

Domain layer throws plain errors; API layer translates to DomainError when needed.

Error propagation across layers

domain throws Error → API catches → returns DomainError(code) → client gets structured error

Do not expose internal error details to clients; map to known error codes or general errors.

Conventions

  • Distinguish programmer vs operational errors; only recover from operational
  • Use DomainError for business validation in API methods; throw for programming bugs
  • Never swallow errors silently; always log or propagate
  • Implement graceful shutdown: stop accepting connections, drain existing, release resources
  • Use retry with exponential backoff for transient failures (network, DB connections)
  • Always handle both uncaughtException and unhandledRejection at process level

Retry pattern

const retry = async (fn, { attempts = 3, delay = 1000 } = {}) => {
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (err) {
      if (i === attempts - 1) throw err;
      await new Promise((r) => setTimeout(r, delay * (i + 1)));
    }
  }
};

Process-level handlers

process.on('uncaughtException', (error) => {
  console.error('Uncaught:', error);
  process.exit(1);
});

process.on('unhandledRejection', (reason) => {
  console.error('Unhandled rejection:', reason);
});

Log and exit on uncaughtException (state may be corrupted). Log unhandledRejection and consider it a bug to fix.

Graceful shutdown

Track connections and drain before exit:

const connections = new Map();

server.on('connection', (conn) => {
  const res = null;
  connections.set(conn, res);
  conn.on('close', () => connections.delete(conn));
});

const shutdown = () => {
  server.close(() => {
    freeResources();
    process.exit(0);
  });
  for (const [conn, res] of connections) {
    if (res) res.end('Server shutting down');
    conn.destroy();
  }
};

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);

Comments

Markdown supported