github/github-mcp-server · error
building installation token URL: %w
Error message
building installation token URL: %w
What it means
url.JoinPath returned an error while composing {BaseRESTURL}/app/installations/{id}/access_tokens. JoinPath parses BaseRESTURL first, so this fires when the configured base is not a valid absolute URL — typically a missing scheme or illegal control characters. It is a configuration error in Config.BaseRESTURL, not a network problem.
Source
Thrown at internal/githubapp/githubapp.go:133
httpClient *http.Client
}
func newInstallationTokenSource(cfg Config, privateKey *rsa.PrivateKey, httpClient *http.Client) *installationTokenSource {
if httpClient == nil {
httpClient = &http.Client{Timeout: httpTimeout}
}
return &installationTokenSource{cfg: cfg, privateKey: privateKey, httpClient: httpClient}
}
func (s *installationTokenSource) Token() (*oauth2.Token, error) {
jwt, err := mintJWT(s.cfg.AppID, s.privateKey, time.Now())
if err != nil {
return nil, err
}
endpoint, err := url.JoinPath(s.cfg.BaseRESTURL, "app", "installations", s.cfg.InstallationID, "access_tokens")
if err != nil {
return nil, fmt.Errorf("building installation token URL: %w", err)
}
ctx, cancel := context.WithTimeout(context.Background(), httpTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, nil)
if err != nil {
return nil, fmt.Errorf("creating installation token request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+jwt)
req.Header.Set("Accept", "application/vnd.github+json")
req.Header.Set("X-GitHub-Api-Version", "2022-11-28")
resp, err := s.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("requesting installation token: %w", err)
}
defer func() { _ = resp.Body.Close() }()View on GitHub (pinned to 0ea1f775a7)
Solutions
- Set BaseRESTURL with an explicit scheme: https://api.github.com/ for github.com, https://HOST/api/v3/ for GitHub Enterprise Server
- Trim whitespace/newlines when loading the value from env or config files
- Validate the URL at startup with url.Parse and check .IsAbs() before constructing the provider
Example fix
// before
cfg := githubapp.Config{BaseRESTURL: os.Getenv("GH_API_URL"), ...} // "ghe.example.com/api/v3"
// after
base := strings.TrimSpace(os.Getenv("GH_API_URL"))
if u, err := url.Parse(base); err != nil || !u.IsAbs() {
return fmt.Errorf("BaseRESTURL %q must be an absolute URL", base)
}
cfg := githubapp.Config{BaseRESTURL: base, ...} Defensive patterns
Strategy: validation
Validate before calling
func validBaseRESTURL(s string) error {
u, err := url.Parse(strings.TrimSpace(s))
if err != nil {
return err
}
if !u.IsAbs() || u.Host == "" {
return fmt.Errorf("%q must be absolute, e.g. https://api.github.com/", s)
}
return nil
} Prevention
- Normalize env-sourced URLs with strings.TrimSpace before use
- Standardize on https://api.github.com/ and https://HOST/api/v3/ via a shared config helper
When it happens
Trigger: Config.BaseRESTURL is set to 'api.github.com' (no https:// scheme), to 'https://api.github.com\n' with a trailing newline from an env var, or contains a control character. url.JoinPath(s.cfg.BaseRESTURL, ...) at internal/githubapp/githubapp.go:131 fails during parsing before any HTTP traffic occurs, so Token() fails immediately on the first call.
Common situations: GITHUB_API_URL or the equivalent env var populated by a script that strips the scheme; GitHub Enterprise Server base like 'https://ghe.example.com/api/v3' mistyped as 'ghe.example.com/api/v3'; YAML/JSON config values carrying stray quotes, backslashes, or CRLF.
Related errors
- creating installation token request: %w
- failed to unmarshal toolsets: %w
- failed to unmarshal tools: %w
- failed to build inventory: %w
- private key is %T, want an RSA key
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/f1b622a1dc68f35e.
Report an issue: GitHub.