github/github-mcp-server · error

failed to create REST client: %w

Error message

failed to create REST client: %w

What it means

GetClient builds the REST client via gogithub.NewClient(WithAuthToken, WithUserAgent, WithEnterpriseURLs(baseRestURL.String(), uploadURL.String())). WithEnterpriseURLs re-parses both URL strings with url.Parse and checks they are absolute; any string the resolver produced that go-github cannot parse becomes this wrapped error. Because the strings come from already-parsed *url.URL values, it is nearly unreachable in the standard wiring and signals a malformed or nil-derived URL in a custom resolver.

Source

Thrown at pkg/github/dependencies.go:332

	token := tokenInfo.Token

	baseRestURL, err := d.apiHosts.BaseRESTURL(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to get base REST URL: %w", err)
	}
	uploadURL, err := d.apiHosts.UploadURL(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to get upload URL: %w", err)
	}

	// Construct REST client
	restClient, err := gogithub.NewClient(
		gogithub.WithAuthToken(token),
		gogithub.WithUserAgent(fmt.Sprintf("github-mcp-server/%s", d.version)),
		gogithub.WithEnterpriseURLs(baseRestURL.String(), uploadURL.String()),
	)
	if err != nil {
		return nil, fmt.Errorf("failed to create REST client: %w", err)
	}
	return restClient, nil
}

// GetGQLClient implements ToolDependencies.
func (d *RequestDeps) GetGQLClient(ctx context.Context) (*githubv4.Client, error) {
	// extract the token from the context
	tokenInfo, ok := ghcontext.GetTokenInfo(ctx)
	if !ok {
		return nil, fmt.Errorf("no token info in context")
	}
	token := tokenInfo.Token

	// Construct GraphQL client
	// We use NewEnterpriseClient unconditionally since we already parsed the API host
	// Wrap transport with GraphQLFeaturesTransport to inject feature flags from context,
	// matching the transport chain used by the remote server.
	gqlHTTPClient := &http.Client{

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Inspect the wrapped error: it is the verbatim go-github/url error and names which URL string failed to parse
  2. Ensure the resolver returns absolute https URLs (scheme + host), e.g. https://api.github.com/ and https://uploads.github.com
  3. Reproduce outside the server: url.Parse(baseRestURL.String()) and url.Parse(uploadURL.String()) in a scratch test to find the malformed component
  4. Percent-encode any tenant or user-supplied path segments before building the URL instead of raw concatenation
  5. Pin/align the go-github version (v89 in this module) so WithEnterpriseURLs validation matches what you tested

Example fix

// before: concatenating an unvalidated host into a URL
restURL := &url.URL{Scheme: "https", Opaque: host + "/api/v3/"} // Opaque stringifies badly
client, err := gogithub.NewClient(gogithub.WithEnterpriseURLs(restURL.String(), uploadURL.String()))

// after: build via structured fields so String() is always parseable
u := &url.URL{Scheme: "https", Host: host, Path: "/api/v3/"}
if err := validateAbsolute(u); err != nil { return nil, err }
client, err := gogithub.NewClient(gogithub.WithEnterpriseURLs(u.String(), upload.String()))
Defensive patterns

Strategy: validation

Validate before calling

// verify both strings are parseable absolute URLs before client construction
for _, s := range []string{baseRestURL.String(), uploadURL.String()} {
	u, err := url.Parse(s)
	if err != nil || !u.IsAbs() {
		return fmt.Errorf("unusable URL for go-github: %q", s)
	}
}

Type guard

func isAbsoluteURL(s string) bool {
	u, err := url.Parse(s)
	return err == nil && u.IsAbs() && u.Host != ""
}

Try / catch

// in GetClient-style code
restClient, err := gogithub.NewClient(opts...)
if err != nil {
	return nil, fmt.Errorf("failed to create REST client: %w", err) // inspect wrapped url.Error via errors.Unwrap
}

Prevention

When it happens

Trigger: A custom APIHostResolver whose URL objects stringify to relative or control-character-laden URLs (e.g. "/api/v3/" with no scheme, or a URL built from unescaped user input); baseRestURL or uploadURL being nil, panicking before this line, in careless implementations; version drift where WithEnterpriseURLs adds new validation. go-github returns url.Parse errors or 'invalid URL' style errors here.

Common situations: Hand-rolled resolvers that construct URLs via string concatenation with unencoded paths; GHES hosts containing spaces or unicode in the hostname; mixed go-github versions after upgrading v89 where URL validation tightened; resolvers that return *url.URL values reconstructed from tenant-supplied headers.

Related errors


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