github/github-mcp-server · warning
GitHub App ID or client ID is required (GITHUB_APP_ID)
Error message
GitHub App ID or client ID is required (GITHUB_APP_ID)
What it means
Raised when json.Marshal(minimalRepos) fails while serializing the []MinimalRepository projection built from the ListStarred response. Every field is an int64/string or a pre-formatted time string (UpdatedAt is formatted with a fixed layout), all of which always marshal. The error exists as a defensive invariant; Go's encoder would need a NaN/Inf, chan, func, or cyclic value to fail, which this projection cannot contain.
Source
Thrown at internal/githubapp/githubapp.go:53
type Config struct {
// AppID is used as the JWT issuer. GitHub accepts an app ID or client ID.
AppID string
// InstallationID identifies the installation whose access token is minted.
InstallationID string
// PrivateKeyPEM is the RSA key used to sign app JWTs.
PrivateKeyPEM []byte
// BaseRESTURL is the REST API base, e.g. https://api.github.com/ for
// github.com or https://HOST/api/v3/ for GitHub Enterprise Server.
BaseRESTURL string
}
func (c Config) validate() error {
switch {
case c.AppID == "":
return errors.New("GitHub App ID or client ID is required (GITHUB_APP_ID)")
case c.InstallationID == "":
return errors.New("GitHub App installation ID is required (GITHUB_APP_INSTALLATION_ID)")
case len(c.PrivateKeyPEM) == 0:
return errors.New("GitHub App private key is required (GITHUB_APP_PRIVATE_KEY_PATH or GITHUB_APP_PRIVATE_KEY)")
case c.BaseRESTURL == "":
return errors.New("GitHub App REST base URL is required")
}
return nil
}
func parsePrivateKey(pemBytes []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, errors.New("no PEM block found in private key")
}
if key, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
return key, nil
}View on GitHub (pinned to 0ea1f775a7)
Solutions
- Treat as a bug: capture owner/username input and report upstream
- Upgrade github-mcp-server to a released version with unmodified DTOs
- If maintaining a fork, keep MinimalRepository fields limited to JSON-safe types
Example fix
// before: fork adds an unsupported field
type MinimalRepository struct {
// ...
Watcher chan struct{} `json:"watcher"` // marshal fails
}
// after
type MinimalRepository struct {
// ...
WatcherCount int `json:"watcher_count"`
} Defensive patterns
Strategy: try-catch
Type guard
func isMarshalError(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to marshal")
} Try / catch
result, _, err := callListStarredRepositories(ctx, username)
if err != nil && isMarshalError(err) {
// internal serialization bug: report upstream with the input; not retryable
log.Printf("marshal bug on starred listing: username=%s err=%v", username, err)
return err
} Prevention
- Run released github-mcp-server versions, not forks with altered DTOs
- Keep MinimalRepository-style projections to strings/ints
- Report immediately if seen - it signals code corruption, not load
When it happens
Trigger: Only reachable if a fork changes MinimalRepository to hold an unmarshalable type (chan, func, *float64 NaN) or a data race corrupts the slice mid-marshal. Stock types decoded and projected from GitHub's API never trigger it.
Common situations: Forked server code adding convenience fields of unsupported types; version skew between a patched go-github and github-mcp-server.
Related errors
- GitHub App authentication and GITHUB_PERSONAL_ACCESS_TOKEN a
- repo is required
- failed to marshal response: %w
- failed to marshal workflow: %w
- failed to marshal workflow run: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/5f72a67af2e33eb9.
Report an issue: GitHub.