How to Implement Custom Error Handling Using the onErrorOccurred Hook in Copilot SDK
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 originalErrorinstancemethod: The RPC method name that triggered the failurerequestId: 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:
- The
ErrorOccurredHandlersignature is declared at line 1512 - The
SessionOptionsinterface includes the optionalonErrorOccurredproperty within itshooksfield at line 1609
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 around line 1870.
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:
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:
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:
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
onErrorOccurredhook is defined asErrorOccurredHandlerinnodejs/src/types.tsat line 1512 and wired intoSessionOptionsat line 1609. - Pass your handler via the
hooksoption when constructing a newSessioninstance. - The handler receives an
ErrorOccurredInfoobject containing the error, method name, and request ID. - Return
trueto indicate the error is handled and suppress propagation; returnfalseto allow the error to bubble up to the caller. - The hook invocation occurs in
nodejs/src/session.tsaround line 1870, 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, 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →