# What Is the process-safety-net and How Does It Prevent Memory Leaks?

> Discover how the process-safety-net global error handler stops memory leaks. Learn how it intercepts transient network errors to prevent process crashes and resource leaks in containers.

- Repository: [Tashfeen/freellmapi](https://github.com/tashfeenahmed/freellmapi)
- Tags: tutorial
- Published: 2026-06-22

---

**The process-safety-net is a global error handler that intercepts transient network-transport errors (like `ECONNRESET` from undici) to prevent unnecessary process crashes, thereby stopping the repeated resource allocation cycles that manifest as memory leaks in containerized deployments.**

In the `tashfeenahmed/freellmapi` repository, the `process-safety-net` module serves as a critical resilience layer for the Node.js server. Without it, transient HTTP/2 socket resets and CDN connection drops trigger fatal process exits that, when combined with automatic restarts in Docker or systemd, create resource churn mistaken for memory leaks. This library swallows only specific transport errors while preserving fail-fast behavior for genuine application bugs.

## Why Uncaught Transport Errors Simulate Memory Leaks

When Node.js encounters an uncaught exception or unhandled promise rejection, it terminates the process with exit code 1. In production environments using container orchestration, this triggers an immediate restart. Each crash and restart cycle abandons open sockets, active timers, and in-memory caches without proper cleanup, then immediately reallocates them upon boot. Over time, this pattern appears as a monotonic memory increase in monitoring dashboards, even though the underlying issue is merely a flaky network transport rather than a true memory leak.

## How the process-safety-net Filters Errors

The implementation in [`server/src/lib/process-safety-net.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/process-safety-net.ts) uses a functional, allow-list approach to distinguish between fatal bugs and recoverable network blips.

### Defining Transport Error Signatures

The library maintains two constant sets that define safe-to-ignore errors:

- `TRANSPORT_ERROR_CODES`: Contains strings like `ECONNRESET`, `UND_ERR_SOCKET`, and other undici-specific error codes
- `TRANSPORT_MESSAGE_HINTS`: Includes substrings like `fetch failed` and `socket hang up` that indicate transient HTTP client failures

These constants form the baseline for the classification logic.

### Walking the Error Chain

Network errors in modern Node.js often nest causes. The `walkErrorChain` function recursively traverses the `err.cause` property of Error objects, collecting every `code` and `message` property into a flat array for inspection.

### Classification Logic

The `isTransportError` function checks if any collected code or message matches the allow-lists. If a match exists, `classifyProcessError` returns the string `'swallow'`; otherwise, it returns `'fatal'`. This ensures that only genuine programming errors or system failures trigger process termination.

### Global Handler Installation

The `installProcessSafetyNet` function registers two process-level listeners:

1. `process.on('uncaughtException', handler)`
2. `process.on('unhandledRejection', handler)`

Both delegate to `handleProcessError`, which logs the decision via a configurable logger and either returns quietly (for transport errors) or calls `process.exit(1)` (for fatal errors).

## Boot Integration in freellmapi

In [`server/src/index.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/index.ts), the safety net installs as the first operation in the `main()` function:

```typescript
import { installProcessSafetyNet } from './lib/process-safety-net.js';

async function main() {
  // Install before any network activity
  installProcessSafetyNet();
  
  // ... remainder of server startup
}

```

This early installation ensures that even errors thrown during the initial `fetch()` calls to upstream LLM APIs are caught and filtered appropriately.

## Customizing Error Handling

The library accepts optional `log` and `exit` hooks for integration with observability platforms:

```typescript
installProcessSafetyNet({
  log: (level, ...args) => {
    myLogger[level]('[safety-net]', ...args);
  },
  exit: (code) => {
    metrics.increment('process.fatal_exit', { code });
    process.exit(code);
  },
});

```

This pattern allows teams to emit structured logs or alert on fatal exits while maintaining silence during routine network hiccups.

## Testing Transport Error Classification

You can verify the classification logic without terminating your process by importing `handleProcessError` directly:

```typescript
import { handleProcessError } from './lib/process-safety-net.js';

// Simulate a CDN socket reset
const err = new Error('socket hang up');
(err as any).code = 'ECONNRESET';

const decision = handleProcessError('uncaughtException', err);
console.log(decision); // 'swallow' - process continues

```

This approach is used in the unit tests at [`server/src/__tests__/lib/process-safety-net.test.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/__tests__/lib/process-safety-net.test.ts) to confirm that transient errors return `'swallow'` while genuine bugs return `'fatal'`.

## Summary

- The **process-safety-net** prevents memory leaks by stopping crash-restart cycles caused by transient network errors like `ECONNRESET`.
- It uses **allow-lists** (`TRANSPORT_ERROR_CODES`, `TRANSPORT_MESSAGE_HINTS`) to identify safe-to-ignore transport failures from `undici` and Node.js HTTP clients.
- The **`walkErrorChain`** and **`isTransportError`** functions recursively inspect nested error causes to make classification decisions.
- **`installProcessSafetyNet`** registers global handlers early in the boot sequence of `tashfeenahmed/freellmapi` to protect against fatal exits during flaky CDN connections.
- Genuine bugs still trigger **`process.exit(1)`** via `handleProcessError`, preserving Node.js fail-fast semantics for non-network errors.

## Frequently Asked Questions

### What specific error codes does the process-safety-net catch?

The safety net specifically watches for transport-layer codes including `ECONNRESET`, `EPIPE`, `UND_ERR_SOCKET`, and `UND_ERR_REQ_RETRY`. It also scans error messages for phrases like `socket hang up` and `fetch failed` to identify transient HTTP/2 connection drops from the `undici` client.

### Does swallowing errors hide memory leaks in my application code?

No. The `process-safety-net` only swallows errors matching the predefined transport error allow-lists. All other exceptions, including actual memory exhaustion (`RangeError: Maximum call stack size exceeded`) or unhandled rejections from application logic, are classified as fatal and trigger immediate `process.exit(1)`. This preserves the fail-fast behavior for genuine bugs.

### Where should I install the process-safety-net in my server?

Install the safety net as the very first operation in your entry point, before any `import` statements that initiate network connections or database pools. In `freellmapi`, this occurs in [`server/src/index.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/index.ts) at the top of the `main()` function, ensuring protection covers the entire application lifecycle including initial upstream API handshakes.

### Can I test the process-safety-net classification logic?

Yes. The module exports `handleProcessError` and `isTransportError` for unit testing. You can pass mock error objects to verify that your specific error conditions are classified correctly as either `swallow` or `fatal` without actually terminating the process, as demonstrated in the project's test suite at [`server/src/__tests__/lib/process-safety-net.test.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/__tests__/lib/process-safety-net.test.ts).