> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shim.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling Guide

> Handle failures gracefully

# Error Handling Guide

Shim returns HTTP 200 for all requests. Check the `success` field and `metadata.errors` array.

***

## Why Always HTTP 200?

**The Problem:**
Your LLM app is in production. A malformed JSON response shouldn't return HTTP 500 and break your frontend.

**The Solution:**
Shim returns structured errors in the response body. Your app stays online.

```json theme={null}
{
  "success": false,
  "repaired": null,
  "metadata": {
    "confidence": "low",
    "errors": [
      {
        "code": "UNRECOVERABLE_SYNTAX_ERROR",
        "message": "The JSON structure is too malformed to repair",
        "severity": "critical",
        "recoverable": false
      }
    ]
  }
}
```

***

## Error Structure

Every error follows this format:

```typescript theme={null}
interface RepairError {
  code: string;           // Error code (e.g., "UNRECOVERABLE_SYNTAX_ERROR")
  message: string;        // Human-readable message
  field?: string;         // Field that caused error (if applicable)
  severity: 'critical' | 'high' | 'medium';
  recoverable: boolean;   // Can you retry?
  suggestion?: string;    // How to fix
}
```

***

## Error Categories

### Request Errors

**INVALID\_REQUEST**

* Missing or invalid parameters
* Recoverable: No
* Fix: Check request body

**PAYLOAD\_TOO\_LARGE**

* Input exceeds 5MB
* Recoverable: No
* Fix: Use streaming or reduce input

### Repair Errors

**UNRECOVERABLE\_SYNTAX\_ERROR**

* JSON structure too malformed to repair after syntax repair
* Recoverable: No
* Fix: Check LLM output format

**SCHEMA\_VALIDATION\_FAILED**

* Repaired JSON doesn't match schema
* Recoverable: No
* Fix: Review schema or LLM prompt

### Session Errors

**SESSION\_NOT\_FOUND**

* Session expired (60s TTL)
* Recoverable: Yes
* Fix: Create new session

**BUFFER\_SIZE\_EXCEEDED**

* Buffer exceeded 5MB (hallucination loop)
* Recoverable: No
* Fix: Add max\_tokens limit to LLM

### Service Errors

**SERVICE\_UNAVAILABLE**

* Server at capacity
* Recoverable: Yes
* Fix: Retry with exponential backoff

**RATE\_LIMIT\_EXCEEDED**

* Exceeded tier limit
* Recoverable: Yes (after wait)
* Fix: Upgrade tier or wait

***

## Checking for Errors

### Basic Check

```typescript theme={null}
const result = await shim.repair({ raw_output: input });

if (!result.success) {
  console.error('Repair failed:', result.metadata.errors);
  return null;
}

return result.repaired;
```

### Check Recoverability

```typescript theme={null}
const result = await shim.repair({ raw_output: input });

if (!result.success) {
  const errors = result.metadata.errors;
  const canRetry = errors.every(e => e.recoverable);

  if (canRetry) {
    // Retry with backoff
    await retryRepair(input);
  } else {
    // Log and alert
    logger.error('Unrecoverable repair error', { errors });
    alertOps('Shim repair failed', errors);
  }
}
```

### Check Specific Error Codes

```typescript theme={null}
const result = await shim.repair({ raw_output: input });

if (!result.success) {
  const error = result.metadata.errors[0];

  switch (error.code) {
    case 'UNRECOVERABLE_SYNTAX_ERROR':
      // LLM output is garbage
      logger.warn('LLM returned invalid output');
      break;

    case 'RATE_LIMIT_EXCEEDED':
      // Hit tier limit
      await new Promise(r => setTimeout(r, 60000)); // Wait 1min
      return retryRepair(input);

    case 'SESSION_NOT_FOUND':
      // Session expired, restart
      return restartSession();

    default:
      logger.error('Unexpected error', { error });
  }
}
```

***

## Retry Strategies

### Exponential Backoff

```typescript theme={null}
async function repairWithBackoff(
  input: string,
  maxRetries = 3
): Promise<any> {
  for (let i = 0; i < maxRetries; i++) {
    const result = await shim.repair({ raw_output: input });

    if (result.success) {
      return result.repaired;
    }

    // Check if recoverable
    const canRetry = result.metadata.errors.every(e => e.recoverable);
    if (!canRetry) {
      throw new Error('Unrecoverable error');
    }

    // Wait before retry: 1s, 2s, 4s
    const delay = Math.pow(2, i) * 1000;
    await new Promise(r => setTimeout(r, delay));
  }

  throw new Error('Max retries exceeded');
}
```

### Circuit Breaker

```typescript theme={null}
class ShimCircuitBreaker {
  private failures = 0;
  private lastFailure = 0;
  private readonly threshold = 5;
  private readonly resetTimeout = 60000; // 1 minute

  async repair(input: string) {
    // Check if circuit is open
    if (this.isOpen()) {
      throw new Error('Circuit breaker open');
    }

    try {
      const result = await shim.repair({ raw_output: input });

      if (result.success) {
        this.reset();
        return result.repaired;
      }

      this.recordFailure();
      throw new Error('Repair failed');
    } catch (error) {
      this.recordFailure();
      throw error;
    }
  }

  private isOpen(): boolean {
    if (this.failures >= this.threshold) {
      const elapsed = Date.now() - this.lastFailure;
      if (elapsed < this.resetTimeout) {
        return true;
      }
      this.reset();
    }
    return false;
  }

  private recordFailure() {
    this.failures++;
    this.lastFailure = Date.now();
  }

  private reset() {
    this.failures = 0;
    this.lastFailure = 0;
  }
}
```

***

## Warnings vs Errors

### Errors (Critical)

Repair failed. `success: false`.

```json theme={null}
{
  "success": false,
  "repaired": null,
  "metadata": {
    "errors": [
      {
        "code": "UNRECOVERABLE_SYNTAX_ERROR",
        "severity": "critical"
      }
    ]
  }
}
```

### Warnings (Non-Critical)

Repair succeeded, but review recommended. `success: true`.

```json theme={null}
{
  "success": true,
  "repaired": { "name": "John" },
  "metadata": {
    "confidence": "medium",
    "warnings": [
      {
        "code": "AMBIGUOUS_REPAIR",
        "message": "Multiple repair interpretations possible",
        "severity": "medium"
      }
    ]
  }
}
```

Handle warnings:

```typescript theme={null}
const result = await shim.repair({ raw_output: input });

if (result.success) {
  // Check warnings
  if (result.metadata.warnings.length > 0) {
    logger.warn('Repair succeeded with warnings', {
      warnings: result.metadata.warnings
    });
  }

  return result.repaired;
}
```

***

## Confidence Levels

Confidence indicates repair safety:

| Level    | Meaning                                 | Action          |
| -------- | --------------------------------------- | --------------- |
| `high`   | Structural fixes only, or perfect input | Use immediately |
| `medium` | Schema repairs or warnings              | Review in logs  |
| `low`    | Ambiguous repairs                       | Manual review   |

```typescript theme={null}
const result = await shim.repair({ raw_output: input });

if (result.success) {
  switch (result.metadata.confidence) {
    case 'high':
      // Safe to use
      return result.repaired;

    case 'medium':
      // Log for review
      logger.info('Medium confidence repair', {
        repairs: result.metadata.repairs_applied
      });
      return result.repaired;

    case 'low':
      // Alert for manual review
      logger.warn('Low confidence repair', {
        repairs: result.metadata.repairs_applied
      });
      alertOps('Low confidence Shim repair');
      return result.repaired;

    // 'high' also covers perfect input (was_repaired: false)
  }
}
```

See [Confidence Levels](/concepts/confidence-levels) for details.

***

## Logging Best Practices

### Log Errors with Context

```typescript theme={null}
const result = await shim.repair({ raw_output: input });

if (!result.success) {
  logger.error('Shim repair failed', {
    errors: result.metadata.errors,
    input_length: input.length,
    request_id: response.headers.get('X-Request-ID')
  });
}
```

### Track Repair Metrics

```typescript theme={null}
const result = await shim.repair({ raw_output: input });

// Track success rate
metrics.increment('shim.repairs.total');
if (result.success) {
  metrics.increment('shim.repairs.success');
} else {
  metrics.increment('shim.repairs.failed');
}

// Track confidence distribution
metrics.increment(`shim.confidence.${result.metadata.confidence}`);

// Track repair types
result.metadata.repairs_applied.forEach(repair => {
  metrics.increment(`shim.repair_type.${repair.type}`);
});
```

### Alert on Failure Spikes

```typescript theme={null}
const failures = await metrics.query('shim.repairs.failed', '5m');
const total = await metrics.query('shim.repairs.total', '5m');
const failureRate = failures / total;

if (failureRate > 0.1) {
  alertOps('High Shim failure rate', {
    rate: failureRate,
    failures,
    total
  });
}
```

***

## Fallback Strategies

### Fallback to Raw Output

```typescript theme={null}
async function repairOrFallback(input: string) {
  const result = await shim.repair({ raw_output: input });

  if (result.success) {
    return result.repaired;
  }

  // Fallback: try parsing raw input
  try {
    return JSON.parse(input);
  } catch {
    // Both failed
    logger.error('Shim and JSON.parse failed');
    return null;
  }
}
```

### Fallback to Default Value

```typescript theme={null}
async function repairOrDefault(input: string, defaultValue: any) {
  const result = await shim.repair({ raw_output: input });

  if (result.success) {
    return result.repaired;
  }

  logger.warn('Using default value due to repair failure');
  return defaultValue;
}
```

### Retry with Looser Schema

```typescript theme={null}
async function repairWithFallback(input: string, schema: JSONSchema) {
  // Try strict mode first
  let result = await shim.repair({
    raw_output: input,
    schema,
    mode: 'strict'
  });

  if (result.success) {
    return result.repaired;
  }

  // Fallback to lenient mode
  logger.warn('Retrying in lenient mode');
  result = await shim.repair({
    raw_output: input,
    schema,
    mode: 'lenient'
  });

  return result.success ? result.repaired : null;
}
```

***

## Production Checklist

* [ ] Check `success` field on every response
* [ ] Log errors with request ID
* [ ] Implement retry logic for recoverable errors
* [ ] Track failure rate metrics
* [ ] Set up alerts for high failure rates
* [ ] Have fallback strategy for critical paths
* [ ] Review low-confidence repairs in logs
* [ ] Monitor repair type distribution

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Error Codes" icon="triangle-exclamation" href="/reference/error-codes">
    Complete error reference
  </Card>

  <Card title="Confidence Levels" icon="gauge" href="/concepts/confidence-levels">
    Understand confidence scoring
  </Card>

  <Card title="Rate Limits" icon="chart-line" href="/guides/rate-limits">
    Handle RATE\_LIMIT\_EXCEEDED
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/troubleshooting">
    Common issues and fixes
  </Card>
</CardGroup>
