github/github-mcp-server · error

failed to get advisory: %w

Error message

failed to get advisory: %w

What it means

Thrown by the get_global_security_advisory MCP tool when client.SecurityAdvisories.GetGlobalSecurityAdvisories returns a non-nil error. The go-github client errors on transport failures (DNS, TLS, timeout, proxy) and also converts non-2xx HTTP responses into *github.ErrorResponse, so the wrapped %w chain usually carries the status code and the GitHub API message.

Source

Thrown at pkg/github/security_advisories.go:366

				},
				Required: []string{"ghsaId"},
			},
		},
		[]scopes.Scope{scopes.SecurityEvents},
		func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
			client, err := deps.GetClient(ctx)
			if err != nil {
				return nil, nil, fmt.Errorf("failed to get GitHub client: %w", err)
			}

			ghsaID, err := RequiredParam[string](args, "ghsaId")
			if err != nil {
				return utils.NewToolResultError(fmt.Sprintf("invalid ghsaId: %v", err)), nil, nil
			}

			advisory, resp, err := client.SecurityAdvisories.GetGlobalSecurityAdvisories(ctx, ghsaID)
			if err != nil {
				return nil, nil, fmt.Errorf("failed to get advisory: %w", err)
			}
			defer func() { _ = resp.Body.Close() }()

			if resp.StatusCode != http.StatusOK {
				body, err := io.ReadAll(resp.Body)
				if err != nil {
					return nil, nil, fmt.Errorf("failed to read response body: %w", err)
				}
				return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get advisory", resp, body), nil, nil
			}

			r, err := json.Marshal(advisory)
			if err != nil {
				return nil, nil, fmt.Errorf("failed to marshal advisory: %w", err)
			}

			result := utils.NewToolResultText(string(r))
			// A global advisory is world-readable (public) but externally

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Verify the advisory ID has the GHSA-xxxx-xxxx-xxxx shape and exists at github.com/advisories
  2. Check the token is set, valid, and issued for the configured host (dotcom vs GHES)
  3. Unwrap the error with errors.As(*github.ErrorResponse) to distinguish 404 vs 401 vs 403 and act accordingly
  4. For transport errors, verify HTTPS_PROXY/egress and retry with backoff

Example fix

// before
advisory, resp, err := client.SecurityAdvisories.GetGlobalSecurityAdvisories(ctx, ghsaID)
if err != nil {
	return nil, nil, fmt.Errorf("failed to get advisory: %w", err)
}

// after - surface API errors as a tool result like the status-code path below it does
advisory, resp, err := client.SecurityAdvisories.GetGlobalSecurityAdvisories(ctx, ghsaID)
if err != nil {
	var ghErr *github.ErrorResponse
	if errors.As(err, &ghErr) {
		return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get advisory", ghErr.Response, []byte(ghErr.Message)), nil, nil
	}
	return nil, nil, fmt.Errorf("failed to get advisory: %w", err)
}
Defensive patterns

Strategy: try-catch

Try / catch

var ghErr *github.ErrorResponse
if errors.As(err, &ghErr) {
	switch ghErr.Response.StatusCode {
	case http.StatusNotFound:
		// treat unknown GHSA id as an empty result, not a crash
	case http.StatusUnauthorized, http.StatusForbidden:
		// surface credential/rate-limit problem to operator
	default:
		// retryable only for 5xx and transport errors
	}
}

Prevention

When it happens

Trigger: Calling the tool with a ghsaId that does not exist (404), a malformed ID (valid shape is GHSA-xxxx-xxxx-xxxx), a token without access, or when the server cannot reach the API host (air-gapped network, corporate proxy, TLS interception, rate limit exhausted).

Common situations: Typos in the GHSA identifier; missing/expired GITHUB_MCP_BACKEND_GITHUB_TOKEN or OAuth token; 403 secondary rate limits; runners without egress to api.github.com; GHES host mismatch between token and configured host.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/866fc0fd32e6d2b4. Report an issue: GitHub.