# OfficeCLI Error Codes and Agent Self-Correction: A Complete Guide

> Understand OfficeCLI error codes and agent self-correction. Learn how OfficeCLI handles errors through numeric codes, configuration, and automatic retries for seamless operation.

- Repository: [OfficeAI/OfficeCLI](https://github.com/iofficeai/OfficeCLI)
- Tags: how-to-guide
- Published: 2026-08-02

---

**OfficeCLI uses a single `OfficeCliError` class with numeric error codes derived from OS/Node.js error numbers, and agents self-correct through error-code inspection, `BatchOptions.stopOnError` configuration, and automatic binary installation with retry logic.**

The OfficeCLI SDK provides a streamlined interface for automating Microsoft Office documents from Node.js applications. When integrations fail, the SDK exposes specific error patterns that autonomous agents can leverage to recover without manual intervention. This guide examines the `OfficeCliError` implementation in [`sdk/node/index.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js), explores how error codes map to failure modes, and demonstrates three self-correction strategies agents employ to maintain resilient document processing pipelines.

---

## OfficeCLI Error Code Architecture

The SDK defines **one unified error type** for all transport and process failures. Unlike libraries that export verbose error enumerations, OfficeCLI derives codes directly from the underlying runtime environment.

### The OfficeCliError Class

In [`sdk/node/index.d.ts`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.d.ts), the error interface appears as:

```typescript
export class OfficeCliError extends Error {
  code: number;
  constructor(message: string, code: number);
}

```

The `code` property carries numeric values corresponding to standard error numbers:

- **ENOENT (2)** — The `officecli` binary cannot be found or executed
- **EPIPE (32)** — The resident process terminated unexpectedly
- **ETIMEDOUT (110)** — A command exceeded the configured timeout threshold

These values originate from [`npm/officecli.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/npm/officecli.js), where the thin wrapper spawns the native binary and translates OS-level failures into structured exceptions.

---

## How Agents Inspect OfficeCLI Error Codes

Since no static enumeration exists, agents must perform **runtime type checking** and numeric code analysis.

### Basic Error Detection Pattern

```typescript
import { open, OfficeCliError } from '@officecli/sdk';

const doc = await open('report.docx');

try {
  await doc.send({ command: 'setText', path: 'p[1]', props: { text: 'Data' } });
} catch (err) {
  if (err instanceof OfficeCliError) {
    // Branch on specific error codes
    switch (err.code) {
      case 2:   // ENOENT
        console.error('Binary missing — autoInstall should handle this');
        break;
      case 32:  // EPIPE
        console.error('Process crashed — safe to retry');
        break;
      case 110: // ETIMEDOUT
        console.error('Network timeout — implement backoff');
        break;
      default:
        console.error(`Unexpected OfficeCLI error: ${err.code}`);
    }
  } else {
    throw err; // Re-throw non-CLI errors
  }
}

```

This pattern from [`sdk/node/index.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js) enables agents to classify failures as **transient** (retryable) or **permanent** (require escalation).

---

## Self-Correction Strategy 1: Batch Configuration with stopOnError

The `BatchOptions` interface in [`sdk/node/index.d.ts`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.d.ts) provides granular control over failure propagation.

### stopOnError Behavior

| Setting | Effect | Use Case |
|---------|--------|----------|
| `true` (default) | Abort entire batch on first failure | Critical transactions requiring atomicity |
| `false` | Continue processing, return partial results | Best-effort bulk operations with per-item recovery |

### Implementation Example

```typescript
import { BatchOptions } from '@officecli/sdk';

const commands = [
  { command: 'setText', path: 'p[1]', props: { text: 'Valid' } },
  { command: 'invalidCommand', path: 'p[2]', props: {} }, // Will fail
  { command: 'setText', path: 'p[3]', props: { text: 'Also Valid' } }
];

const opts: BatchOptions = { stopOnError: false };
const result = await doc.batch(commands, opts);

// result contains success/failure status per item
console.log('Processed:', result.completed.length, 'of', commands.length);

```

Agents using `stopOnError: false` can iterate through partial results, identify failed indices, and construct targeted retry batches.

---

## Self-Correction Strategy 2: Automatic Binary Installation

The `OpenOptions.autoInstall` flag eliminates a common failure mode before it occurs.

### How autoInstall Works

```typescript
import { open } from '@officecli/sdk';

// Default behavior: fetch and install binary if absent
const doc = await open('document.docx', { autoInstall: true });

```

When `autoInstall: true` (the default), [`npm/officecli.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/npm/officecli.js) performs these steps:

1. Checks for `officecli` in `PATH` and standard installation directories
2. Downloads platform-appropriate binary from the OfficeCLI release CDN
3. Verifies checksum and sets executable permissions
4. Proceeds with document initialization

This prevents `ENOENT` errors during cold starts, particularly in containerized or CI/CD environments where binaries aren't pre-installed.

---

## Self-Correction Strategy 3: Exponential Backoff Retry Loops

For transient failures like `EPIPE` or `ETIMEDOUT`, agents implement **context-aware retry logic** that respects error semantics.

### Production-Ready Retry Pattern

```typescript
async function resilientSend(doc, command, maxRetries = 3) {
  const delays = [1000, 2000, 4000]; // Exponential backoff schedule
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await doc.send(command);
    } catch (err) {
      if (!(err instanceof OfficeCliError)) throw err;
      
      // Only retry transient error codes
      const retryableCodes = [32, 110]; // EPIPE, ETIMEDOUT
      if (!retryableCodes.includes(err.code) || attempt === maxRetries - 1) {
        throw err; // Permanent failure or exhausted retries
      }
      
      console.warn(`Attempt ${attempt + 1} failed, retrying in ${delays[attempt]}ms`);
      await new Promise(r => setTimeout(r, delays[attempt]));
    }
  }
}

```

This approach distinguishes between:

- **Retryable**: Process crashes, network timeouts, resource contention
- **Non-retryable**: Missing files, permission errors, malformed commands

---

## Complete Agent Integration Example

Combining all three strategies yields a fault-tolerant document processor:

```typescript
import { open, OfficeCliError, BatchOptions } from '@officecli/sdk';

class ResilientDocumentAgent {
  async processBulk(docPath: string, items: any[]) {
    const doc = await open(docPath, { autoInstall: true });
    
    const opts: BatchOptions = { stopOnError: false };
    const batchResult = await doc.batch(items, opts);
    
    // Retry individual failures with backoff
    const recoverable = batchResult.failed.filter(f => 
      f.error.code === 32 || f.error.code === 110
    );
    
    for (const failure of recoverable) {
      try {
        const retry = await this.withBackoff(() => 
          doc.send(failure.command)
        );
        batchResult.completed.push(retry);
      } catch (finalError) {
        batchResult.permanentFailures.push(finalError);
      }
    }
    
    return batchResult;
  }
  
  private async withBackoff<T>(operation: () => Promise<T>, attempts = 3): Promise<T> {
    // Exponential backoff implementation
    for (let i = 0; i < attempts; i++) {
      try {
        return await operation();
      } catch (err) {
        if (i === attempts - 1) throw err;
        await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
      }
    }
    throw new Error('Unreachable');
  }
}

```

---

## Summary

OfficeCLI error handling centers on the `OfficeCliError` class with numeric codes reflecting OS/Node.js error numbers:

- **Inspect `err.code`** to classify failures as transient or permanent
- **Configure `BatchOptions.stopOnError`** to control failure propagation in bulk operations
- **Enable `autoInstall`** to eliminate binary availability failures
- **Implement backoff retries** for `EPIPE` (32) and `ETIMEDOUT` (110) scenarios

Key source files implementing this behavior: [`sdk/node/index.d.ts`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.d.ts) (type definitions), [`sdk/node/index.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js) (runtime error construction), and [`npm/officecli.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/npm/officecli.js) (binary wrapper and `autoInstall` logic).

---

## Frequently Asked Questions

### What error codes does OfficeCliError use?

OfficeCliError carries numeric codes derived from standard POSIX and Node.js error numbers. Common values include 2 (ENOENT, missing binary), 32 (EPIPE, crashed process), and 110 (ETIMEDOUT, network timeout). The SDK does not export a static enumeration — agents must check `err.code` numerically against expected values.

### How do I make a batch operation continue after individual failures?

Pass `{ stopOnError: false }` as the second argument to `doc.batch()`. This returns partial results rather than throwing on the first failure, allowing your agent to analyze which commands succeeded and retry only the failed subset.

### Can OfficeCLI automatically fix a missing binary?

Yes. The `autoInstall` option in `OpenOptions` (default `true`) triggers automatic download and installation of the platform-appropriate `officecli` binary. This prevents ENOENT errors during initial document opening, particularly useful in ephemeral environments like Docker containers or CI runners.

### When should an agent retry versus abort?

Retry transient errors: process crashes (code 32) and timeouts (code 110) typically resolve with backoff. Abort permanent errors: missing files, permission denials, or malformed commands indicate configuration issues that retries cannot fix. Inspect `err.code` and maintain an allowlist of retryable values.