# Desktop Commander MCP Error Handling Strategy: 5 Layers of Safe, Consistent Failure Management

> Discover the Desktop Commander MCP error handling strategy. Learn how its 5 layers ensure safe, consistent failure management with central error capture and uniform ServerResult objects.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: architecture
- Published: 2026-08-02

---

**Desktop Commander MCP uses a five-layer error handling strategy that captures errors centrally, sanitizes sensitive data for telemetry, and returns uniform ServerResult objects to all consumers.**

The `wonderwhy-er/DesktopCommanderMCP` repository implements a **defensive, privacy-first error handling strategy** designed for an AI-powered desktop automation server. Every failure follows a predictable path: capture for diagnostics, sanitize for privacy, and standardize for API consistency. This article breaks down exactly how the codebase handles runtime errors without leaking sensitive information.

---

## Layer 1: Central Capture and Sanitization in [`capture.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/capture.ts)

All errors flow through **[`src/utils/capture.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/capture.ts)**, the telemetry gateway. The **`capture()`** function records failures for monitoring while **`sanitizeError()`** strips personally identifiable information before data leaves the process.

```typescript
// src/utils/capture.ts – simplified sanitization logic
export function sanitizeError(error: any): { message: string; code?: string } {
  if (typeof error === 'string') {
    return { message: error };
  }
  if (error && typeof error.message === 'string') {
    // Strip file paths and credential fragments
    const clean = error.message.replace(/([A-Za-z]:\\|\/)[^\s]*/g, '[REDACTED]');
    return { message: clean, code: error.code };
  }
  return { message: 'Unknown error' };
}

```

The sanitization applies **only to telemetry payloads**. The original error remains intact for internal debugging, ensuring accurate diagnostics without privacy violations. As noted in the source: *"Don't sanitize operation name for logs – only telemetry will sanitize if needed."*

---

## Layer 2: Uniform ServerResult API Contract

Every public function returns a **`ServerResult`** object. Errors set **`isError: true`** and provide a plain-text description in the **`content`** array. This structure guarantees that **UI components, CLI clients, and remote MCP consumers** parse responses identically.

The **`createErrorResponse()`** helper in **[`src/error-handlers.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/error-handlers.ts)** constructs these objects:

```typescript
// src/error-handlers.ts – central error response builder
export function createErrorResponse(message: string): ServerResult {
  // Record for telemetry (sanitized inside capture)
  capture('server_request_error', { error: message });

  // Return standardized shape
  return {
    content: [{ type: 'text', text: `Error: ${message}` }],
    isError: true,
  };
}

```

This single function eliminates inconsistent error shapes across the codebase.

---

## Layer 3: Defensive Try/Catch Wrappers

Core tools wrap operations in **`try { … } catch (e) { … }`** blocks. The catch handler forwards errors to **`capture()`** for telemetry, then transforms them into safe user-facing messages via **`createErrorResponse()`**.

Real-world example from file system operations:

```typescript
import { capture } from './utils/capture.js';
import { createErrorResponse } from './error-handlers.js';
import { readFile } from 'fs/promises';

export async function readUserFile(path: string): Promise<ServerResult> {
  try {
    const data = await readFile(path, 'utf8');
    return { content: [{ type: 'text', text: data }], isError: false };
  } catch (e) {
    // Telemetry: recorded and sanitized automatically
    capture('file_read_error', { error: e });

    // User response: safe, uniform message
    const safeMessage = typeof e === 'object' && e?.message
      ? e.message
      : String(e);
    return createErrorResponse(safeMessage);
  }
}

```

This pattern appears throughout **[`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts)**, **[`src/utils/withTimeout.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/withTimeout.ts)**, and **[`src/utils/trackTools.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/trackTools.ts)**.

---

## Layer 4: Controlled Logging with [`logger.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/logger.ts)

The lightweight logger in **[`src/utils/logger.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/logger.ts)** writes concise console messages when **`DEBUG`** mode is enabled. It **never prints raw error objects**, preventing accidental data exposure in production logs.

Usage pattern:

```typescript
import { logger } from './utils/logger.js';

logger.error('File read operation failed');
// Output (DEBUG=1): "ERROR: File read operation failed"
// Output (DEBUG=0): silent

```

---

## Layer 5: Telemetry-Only Data Flow

The Desktop Commander MCP error handling strategy maintains **separation between diagnostics and user feedback**:

| Path | Data Treatment | Destination |
|------|---------------|-------------|
| Telemetry | Sanitized via `sanitizeError()` | BigQuery / analytics backends |
| User response | Original message (safe context) | `ServerResult.content` |
| Debug logs | Conditionally enabled, no raw objects | Console (development only) |

This design prevents the common failure mode of "over-sanitization" that strips useful context from user-facing errors.

---

## Complete Error Flow: Step-by-Step

1. **Operation initiates** – async I/O or tool execution begins
2. **Exception caught** – `try/catch` block intercepts the failure
3. **Telemetry recorded** – `capture()` receives raw error; `sanitizeError()` cleans PII before external transmission
4. **Response constructed** – `createErrorResponse()` builds `ServerResult` with `isError: true`
5. **Result returned** – calling REPL, UI, or MCP client receives uniform object

---

## Key Files in the Error Handling Architecture

| File | Responsibility |
|------|--------------|
| [`src/utils/capture.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/capture.ts) | Central telemetry hook with `sanitizeError()` |
| [`src/error-handlers.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/error-handlers.ts) | `createErrorResponse()` and related helpers |
| [`src/utils/logger.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/logger.ts) | Conditional debug logging |
| [`src/utils/withTimeout.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/withTimeout.ts) | Timeout wrapper demonstrating error forwarding |
| [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) | Production tool implementation with full error pipeline |

---

## Summary

Desktop Commander MCP's error handling strategy delivers three core guarantees:

- **Consistent API contracts** via the `ServerResult` type and `createErrorResponse()` helper
- **Privacy-preserving telemetry** through [`capture.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/capture.ts) and `sanitizeError()`
- **Clear user feedback** with defensive `try/catch` patterns in every tool function

The layered approach separates concerns cleanly: diagnostics happen invisibly, sensitive data stays protected, and every client receives predictable, parseable responses.

---

## Frequently Asked Questions

### How does Desktop Commander MCP prevent sensitive data leaks in error messages?

The `sanitizeError()` function in [`src/utils/capture.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/capture.ts) uses regex patterns to detect and redact file paths, credentials, and other PII from telemetry payloads. This sanitization applies only to external analytics; user-facing error messages retain original context for debugging assistance.

### What is the ServerResult type and why is it important?

`ServerResult` is a standardized response object with `content` (text array), `isError` (boolean), and optional metadata. It ensures that UI layers, CLI tools, and remote MCP clients all parse success and failure states identically, eliminating integration bugs from inconsistent error shapes.

### Where should I add error handling for new tools in this codebase?

Wrap your tool's main operation in `try/catch`, call `capture('your_tool_error', { error: e })` for telemetry, and return `createErrorResponse(message)` on failure. Follow the pattern in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) for production-ready implementation.

### Does the DEBUG flag affect error reporting behavior?

Yes. When `DEBUG=1`, `logger.error()` and related methods write to console. However, raw error objects are never printed—only safe, stringified messages—to maintain privacy even in development environments.