# How OpenAI Plugins Error Handling Works: A Three-Layer Architecture

> Understand how OpenAI plugins error handling works with a three-layer architecture. Learn about runtime wrappers, OpenAPI validation, and developer try-catch blocks for structured JSON errors.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: architecture
- Published: 2026-06-14

---

**OpenAI plugins handle errors through a three-layer system: a runtime wrapper that catches uncaught exceptions, an OpenAPI specification that validates error schemas, and developer-implemented try-catch blocks that return structured JSON error objects.**

OpenAI plugins execute user-provided skill scripts inside a sandboxed runtime environment defined in the `openai/plugins` repository. When an API call fails or code throws an exception, the platform converts these failures into standardized JSON error responses that clients can handle predictably.

## The Three-Layer Error Handling Architecture

Error handling in the OpenAI plugins system operates through three distinct layers that ensure every failure mode surfaces as a machine-readable error object.

### 1. Runtime Wrapper Layer (Automatic Exception Catching)

Every skill script executes inside an automatic wrapper that functions as the first line of defense against unhandled exceptions. According to [`plugins/figma/skills/figma-use/references/plugin-api-standalone.d.ts`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/references/plugin-api-standalone.d.ts), the runtime wraps each skill in an async IIFE (Immediately Invoked Function Expression) or equivalent Python construct that catches any uncaught exception. When an exception occurs, the wrapper translates it into a structured error payload with an HTTP `5xx` status code, returning a JSON object containing `{ "error": { "code": "internal", "message": "<exception details>" } }`.

### 2. OpenAPI Specification Layer (Schema Validation)

Each plugin ships with an OpenAPI specification file (referenced in `<plugin>/.app.json` files such as [`plugins/google-calendar/.app.json`](https://github.com/openai/plugins/blob/main/plugins/google-calendar/.app.json)) that defines the contract between the plugin and the OpenAI platform. This specification includes a `default` response schema describing the exact shape of error objects, typically requiring fields like `code`, `message`, and optional `details`. The OpenAI server validates every response against this schema, automatically mapping any non-`2xx` response to the client's `error` field before forwarding it.

### 3. Developer-Controlled Error Handling

Within skill scripts, developers implement explicit error handling for anticipated failure modes such as network timeouts, API authentication failures, or validation errors. As demonstrated in [`plugins/zotero/skills/zotero/scripts/zotero.py`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/scripts/zotero.py), developers catch specific exceptions and return structured error objects with appropriate `4xx` status codes for client errors. This layer allows for semantic error codes (like `"invalid_token"` or `"rate_limited"`) that help downstream systems make intelligent retry decisions.

## Error Handling Implementation Examples

### Python Error Handling Pattern

The Zotero skill demonstrates the recommended pattern for handling both expected and unexpected failures:

```python
import json
import requests

def fetch_items():
    try:
        resp = requests.get("https://api.zotero.org/users/123/items")
        resp.raise_for_status()
        return {"data": resp.json()}
    except requests.HTTPError as exc:
        # Known API error – return a client‑error payload

        return {"error": {"code": "client", "message": str(exc)}}
    except Exception as exc:
        # Unexpected error – surface as internal error

        return {"error": {"code": "internal", "message": str(exc)}}

```

### TypeScript Error Handling Pattern

For TypeScript skills, the runtime implements similar wrapping logic. A manual implementation following the patterns from the Figma skill would look like:

```typescript
export async function run(context: PluginContext) {
  try {
    const nodes = await figma.currentPage.findAll(node => node.type === "RECTANGLE");
    return { data: nodes.map(n => n.id) };
  } catch (err) {
    // Propagate the error to the OpenAI platform
    return { error: { code: "internal", message: (err as Error).message } };
  }
}

```

## Best Practices for Robust Error Handling

According to [`plugins/cloudflare/skills/workers-best-practices/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/cloudflare/skills/workers-best-practices/SKILL.md), developers should distinguish between transient failures (which may benefit from automatic retries) and persistent errors (which should propagate immediately). The documentation recommends using explicit `try...catch` blocks rather than relying solely on the runtime wrapper, as this allows for more specific error codes and user-friendly messages.

Additionally, [`plugins/zoom/skills/video-sdk/windows/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/video-sdk/windows/SKILL.md) suggests architectural patterns that improve reliability, such as separating session initialization from audio initialization. This separation allows for granular error handling where network failures during session join can be caught and reported independently from hardware initialization errors.

## Summary

- **Runtime wrapper**: Automatically catches uncaught exceptions in [`plugins/figma/skills/figma-use/references/plugin-api-standalone.d.ts`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/references/plugin-api-standalone.d.ts) and converts them to `5xx` internal errors.
- **OpenAPI schema**: Validates error response structure through [`.app.json`](https://github.com/openai/plugins/blob/main/.app.json) specifications, ensuring consistent JSON formatting across all plugins.
- **Developer implementation**: Uses explicit `try...except` blocks (as shown in [`plugins/zotero/skills/zotero/scripts/zotero.py`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/scripts/zotero.py)) to return semantic `4xx` errors for client-side failures.
- **Structured responses**: All errors must return JSON objects with an `error` key containing `code` and `message` fields.

## Frequently Asked Questions

### What happens when a plugin throws an uncaught exception?

The runtime wrapper defined in the plugin's TypeScript definitions (such as [`plugins/figma/skills/figma-use/references/plugin-api-standalone.d.ts`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/references/plugin-api-standalone.d.ts)) automatically catches the exception and converts it into a JSON error response with an HTTP `5xx` status code. The wrapper returns an object containing `{ "error": { "code": "internal", "message": "<exception details>" } }` to ensure the client receives a valid JSON response even when the skill script crashes.

### How should I structure error responses in my plugin?

Error responses must follow the schema defined in your plugin's OpenAPI specification (referenced in your [`.app.json`](https://github.com/openai/plugins/blob/main/.app.json) file). Return a JSON object containing an `error` key with at minimum `code` and `message` fields. Use `"client"` or specific semantic codes (like `"invalid_token"`) for `4xx` errors, and reserve `"internal"` for unexpected server-side failures that warrant a `5xx` status.

### Does the OpenAI platform retry failed plugin requests?

The platform may automatically retry requests for certain transient failures, particularly network timeouts or rate-limit responses. However, persistent errors—those returning client-side `4xx` codes or explicit internal errors—propagate unchanged to the client. According to [`plugins/cloudflare/skills/workers-best-practices/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/cloudflare/skills/workers-best-practices/SKILL.md), developers should design idempotent operations where possible to safely support potential retries.

### Where is the error schema defined for OpenAI plugins?

The error response schema is defined in each plugin's OpenAPI specification file, typically located under the plugin directory and referenced in the [`.app.json`](https://github.com/openai/plugins/blob/main/.app.json) configuration file (such as [`plugins/google-calendar/.app.json`](https://github.com/openai/plugins/blob/main/plugins/google-calendar/.app.json)). The `default` response in the OpenAPI spec describes the required error object structure that the platform validates against before forwarding responses to clients.