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

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, 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, the error interface appears as:

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, 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

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 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 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

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

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 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

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:

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 (type definitions), sdk/node/index.js (runtime error construction), and 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →