# How to Implement Custom Error Handling Using the onErrorOccurred Hook in Copilot SDK

> Implement custom error handling in Copilot SDK with onErrorOccurred. Log transform or swallow errors before they reach your app. Learn more in this guide.

- Repository: [GitHub/copilot-sdk](https://github.com/github/copilot-sdk)
- Tags: how-to-guide
- Published: 2026-08-02

---

**You can intercept runtime errors in the Copilot SDK by supplying an `onErrorOccurred` function in the `hooks` option when instantiating a `Session`, allowing you to log, transform, or swallow errors before they propagate to your application.**

The Copilot SDK provides a robust session-based architecture for interacting with GitHub Copilot models, and proper error handling is critical for production stability. By leveraging the **`onErrorOccurred`** hook available in the session configuration, developers can customize how the SDK responds to transport failures, protocol errors, and unexpected runtime exceptions. This guide demonstrates how to implement custom error handling using the exact type definitions and session patterns found in the `github/copilot-sdk` source code.

## Understanding the Hook Architecture

The SDK exposes error handling through the **`ErrorOccurredHandler`** type defined in the core types file. When you create a new `Session`, the constructor accepts a `hooks` object containing an optional `onErrorOccurred` property. During the session lifecycle, any error that bubbles up from the underlying JSON-RPC connection—whether a network `ConnectionError`, a malformed `ResponseError`, or a transaction failure—gets forwarded to your handler.

The handler receives an **`ErrorOccurredInfo`** object containing:
- `error`: The original `Error` instance
- `method`: The RPC method name that triggered the failure
- `requestId`: The unique identifier for the request context

Your handler must return a `boolean` (or `Promise<boolean>`). Returning `true` signals that you have handled the error and the SDK should suppress further propagation. Returning `false` allows the error to continue bubbling up to the caller.

## Type Definitions and Configuration

The type definitions that govern this behavior reside in [`nodejs/src/types.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts):

- The **`ErrorOccurredHandler`** signature is declared at [line 1512](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts#L1512)
- The **`SessionOptions`** interface includes the optional `onErrorOccurred` property within its `hooks` field at [line 1609](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts#L1609)

When the session processes an RPC call and catches an exception, it delegates to your hook via the internal `hooks` object. This invocation point is implemented in [`nodejs/src/session.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts) around [line 1870](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts#L1870).

## Implementing a Basic Error Logger

For most applications, the first step is capturing error details for observability. The following example shows a minimal handler that logs errors to the console and marks them as handled:

```typescript
import { Session, SessionOptions, ErrorOccurredHandler } from "@github/copilot-sdk";

const loggingHandler: ErrorOccurredHandler = (info) => {
  console.error("[Copilot SDK Error]", {
    message: info.error.message,
    method: info.method,
    requestId: info.requestId,
    stack: info.error.stack,
  });
  // Return true to prevent the error from propagating to the caller
  return true;
};

const options: SessionOptions = {
  // ... other required configuration (authToken, model, etc.)
  hooks: {
    onErrorOccurred: loggingHandler,
  },
};

const session = new Session(options);

```

This pattern ensures that transient network glitches or model errors are captured without crashing your application logic.

## Advanced Error Handling Patterns

Production applications often require sophisticated logic to distinguish between retryable transient failures and critical errors that demand immediate attention.

### Retry Logic for Transient Failures

You can implement asynchronous handlers to perform cleanup or retry logic before deciding whether to propagate the error. This example detects `ConnectionError` instances and implements a brief backoff before allowing the SDK to retry:

```typescript
import { Session, SessionOptions, ErrorOccurredInfo, ConnectionError } from "@github/copilot-sdk";

async function retryableErrorHandler(info: ErrorOccurredInfo): Promise<boolean> {
  if (info.error instanceof ConnectionError) {
    console.warn(`Network error in ${info.method}, applying backoff...`);
    await new Promise(resolve => setTimeout(resolve, 1000));
    
    // Return false to let the SDK propagate and potentially retry the RPC
    return false;
  }
  
  // Log non-network errors and swallow them
  console.error("Critical SDK error:", info.error);
  return true;
}

const session = new Session({
  // ... configuration
  hooks: {
    onErrorOccurred: retryableErrorHandler,
  },
});

```

### Error Classification and Telemetry

For applications integrated with monitoring systems, classify errors by type before sending them to your telemetry pipeline:

```typescript
import { Session, ErrorOccurredInfo, ResponseError } from "@github/copilot-sdk";
import { trackException } from "./monitoring";

function telemetryHandler(info: ErrorOccurredInfo): boolean {
  const severity = info.error instanceof ResponseError ? "warning" : "error";
  
  trackException({
    error: info.error,
    properties: {
      rpcMethod: info.method,
      requestId: info.requestId,
      severity: severity,
    },
  });
  
  // Allow the SDK's default error handling to continue
  return false;
}

const session = new Session({
  hooks: { onErrorOccurred: telemetryHandler },
});

```

## Summary

- The **`onErrorOccurred`** hook is defined as `ErrorOccurredHandler` in [`nodejs/src/types.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts) at [line 1512](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts#L1512) and wired into `SessionOptions` at [line 1609](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts#L1609).
- Pass your handler via the `hooks` option when constructing a new `Session` instance.
- The handler receives an `ErrorOccurredInfo` object containing the error, method name, and request ID.
- Return `true` to indicate the error is handled and suppress propagation; return `false` to allow the error to bubble up to the caller.
- The hook invocation occurs in [`nodejs/src/session.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts) around [line 1870](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts#L1870), ensuring all RPC-level errors pass through your custom logic.

## Frequently Asked Questions

### What types of errors can the onErrorOccurred hook capture?

The hook intercepts any error that originates from the SDK's JSON-RPC layer, including `ConnectionError` (network failures), `ResponseError` (malformed or invalid protocol responses), and `SessionFsSqliteTransactionError` (local storage transaction failures). According to the implementation in [`session.ts`](https://github.com/github/copilot-sdk/blob/main/session.ts), the hook acts as a catch-all for the session's internal error bubbling mechanism.

### Can the onErrorOccurred handler be asynchronous?

Yes, the `ErrorOccurredHandler` type supports both synchronous and asynchronous implementations. The SDK awaits the handler's result before determining whether to propagate the error, allowing you to perform async cleanup, logging, or external API calls within your error handling logic.

### How does the return value affect error propagation?

When your handler returns `true`, the SDK treats the error as resolved and stops propagation immediately. If you return `false`, the original error continues to bubble up through the call stack, eventually reaching the code that initiated the RPC call (e.g., `session.complete()` or `session.chat()`), where it can be caught with standard try/catch blocks.

### Is it possible to modify the error before it propagates?

While you cannot directly mutate the error object that continues propagating (since the handler returns a boolean rather than an error), you can clone or wrap the error within your handler, log the modified version, and then return `false` to propagate the original. For transformation use cases, consider implementing a wrapper around the Session methods rather than using the hook alone.