Error Handling Patterns
Relevant source files
The following files were used as context for generating this wiki page:
Error handling in the GitHub MCP Server is designed to bridge the gap between GitHub's upstream APIs (REST and GraphQL) and the Model Context Protocol (MCP) result format. The system employs a context-based error tracking mechanism that allows for error accumulation and inspection, especially useful in middleware and complex tool execution flows.
The architecture ensures that even when a tool returns an error result to the LLM, the underlying technical details—such as HTTP status codes or GraphQL mutation failures—are captured and accessible for logging or debugging within the request context.
Contextual Error Tracking
The project implements a pattern where errors are stored within the context.Context. This is achieved by initializing a context with specific error tracking capabilities, allowing subsequent service calls to attach detailed GitHub API or GraphQL errors without requiring explicit error propagation through every function signature.
Error Accumulation Flow
When a tool or service call fails, the error handler captures the original error along with relevant metadata (like the HTTP response). These are appended to a slice stored in the context pointer.
The diagram shows how errors are captured and stored in a shared context slice during execution. Sources: pkg/errors/error_test.go:104-135
Shared Pointer Behavior
A key technical detail is the use of pointer sharing for the error slice. This allows middleware that captured the context early in the request lifecycle to see errors that were added much later by deep business logic, even if the updated context was not propagated back up the call stack. Sources: pkg/errors/error_test.go:104-115
GitHub API Error Handling
GitHub REST API errors are handled by wrapping the standard error and the github.Response object. This provides access to HTTP status codes (e.g., 404, 403, 422) which are critical for determining the nature of the failure.
Capture Methods
| Function | Purpose | Derived From |
|---|---|---|
NewGitHubAPIErrorToCtx | Adds a REST API error to the context slice. | pkg/errors/error_test.go:26-30 |
NewGitHubAPIErrorResponse | Creates an MCP error result and stores the error in context. | pkg/errors/error_test.go:171-175 |
GetGitHubAPIErrors | Retrieves all captured REST errors from a context. | pkg/errors/error_test.go:33-35 |
Implementation in Tools
Tools typically check the status code of the GitHub response. If it is not the expected successful status (e.g., http.StatusOK or http.StatusCreated), the tool reads the response body and returns an MCP-compliant error result.
// Example pattern in issues.go
if resp.StatusCode != http.StatusCreated {
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
return mcp.NewToolResultError(fmt.Sprintf("failed to create comment: %s", string(body))), nil
}
Sources: pkg/github/issues.go:310-316
GraphQL Error Handling
GraphQL errors are handled separately from REST errors because GraphQL often returns a 200 OK status even when the query or mutation contains errors in the response body.
GraphQL Error Logic
The system captures mutation failures or query resolution issues (like "Could not resolve to a node with the ID...") and stores them as GitHubGraphQLError objects.
The sequence demonstrates the GraphQL error capture flow used in mutations like closing or reopening issues. Sources: pkg/github/issues.go:810-825, pkg/errors/error_test.go:195-200
Validation and Parameter Errors
Before calling upstream APIs, tools perform validation on input parameters. These errors are returned immediately as MCP error results to prevent unnecessary API calls and provide immediate feedback to the LLM.
Common Validation Patterns
- Required Parameters: Tools use helper functions like
RequiredParam[string]orRequiredIntto validate presence. - Mutual Exclusivity: Logic checks if conflicting parameters are provided (e.g., specifying both
after_idandbefore_idin sub-issue reprioritization). - Format Validation: Timestamp strings are validated against ISO 8601/RFC3339 formats before being processed.
| Validation Type | Example Tool | Description |
|---|---|---|
| Missing Required | GetIssue | Errors if owner, repo, or issue_number is missing. |
| Parameter Logic | ReprioritizeSubIssue | Errors if neither or both after_id and before_id are provided. |
| Type Mismatch | SearchIssues | Validates that pagination parameters are numbers. |
| Format Check | ListIssues | parseISOTimestamp ensures the since parameter is valid. |
Sources: pkg/github/issues.go:210-220, pkg/github/issues.go:540-550, pkg/github/issues.go:1010-1030
Summary of Patterns
The project consistently follows these three patterns for error management:
- Immediate Return for Validation: Input validation happens first; failures return an MCP error result without side effects. Sources: pkg/github/issues_test.go:1100-1115
- Contextual Capture for APIs: All upstream GitHub failures are recorded in the context, allowing for rich telemetry and debugging via middleware. Sources: pkg/errors/error_test.go:220-260
- Graceful Uninitialized Handling: Error retrieval functions are designed to handle uninitialized contexts (contexts without error tracking enabled) gracefully, returning descriptive errors rather than panicking. Sources: pkg/errors/error_test.go:205-215
Error handling serves as a translation layer, converting technical Go errors and HTTP failures into structured text messages that an AI model can interpret and act upon. Sources: pkg/github/security_advisories_test.go:75-85