github/github-mcp-server · error
requesting device code: %w
Error message
requesting device code: %w
What it means
The initial device-authorization request (oc.DeviceAuth) failed, so the device flow cannot even be prepared. Bounded by the 30-second deviceAuthTimeout, it fails on network errors, non-200 responses from the device code endpoint, or GitHub rejecting the app (e.g. client credentials wrong, or the endpoint unreachable on older GitHub Enterprise Server). Because this happens during flow preparation, the caller gets the error immediately rather than at run time.
Source
Thrown at internal/oauth/flow.go:166
})
}
return &flowPlan{run: run, display: display, fallback: manual}, nil
}
return &flowPlan{run: run, userAction: manual}, nil
}
// beginDevice prepares the device authorization flow. It requests a device code
// up front (so the code can be displayed) and selects a display channel:
// URL elicitation, then form elicitation, then a tool-response message.
func (m *Manager) beginDevice(prompter Prompter) (*flowPlan, error) {
oc := m.oauth2Config("")
ctx, cancel := context.WithTimeout(context.Background(), deviceAuthTimeout)
defer cancel()
da, err := oc.DeviceAuth(ctx)
if err != nil {
return nil, fmt.Errorf("requesting device code: %w", err)
}
run := func(ctx context.Context) (*oauth2.Token, error) {
tok, err := oc.DeviceAccessToken(ctx, da)
if err != nil {
return nil, fmt.Errorf("awaiting device authorization: %w", err)
}
return tok, nil
}
// As with PKCE, the manual instructions double as the runtime fallback, so
// build them once and reuse for both display plans and the last resort.
manual := &UserAction{
URL: da.VerificationURI,
UserCode: da.UserCode,
Message: fmt.Sprintf(
"%s\n\nAfter authorizing, retry your request.\n\n%s",
deviceInstruction(da), securityAdvisory,View on GitHub (pinned to 0ea1f775a7)
Solutions
- Verify reachability of the device endpoint: curl -X POST https://github.com/login/device/code from the same host
- Confirm the OAuth app's client ID/secret are current (rotated secrets are the classic 401 here)
- On GHES, upgrade to a version supporting the device flow or use a PAT/app installation auth instead
- If PKCE also failed, fix the primary cause (see 115/116) rather than relying on device flow
Defensive patterns
Strategy: try-catch
Validate before calling
func deviceEndpointReachable() bool {
c := &http.Client{Timeout: 5 * time.Second}
resp, err := c.Post("https://github.com/login/device/code", "application/json", nil)
return err == nil && resp != nil // any status (even 4xx) proves reachability
} Try / catch
if err != nil && strings.Contains(err.Error(), "requesting device code") {
// 401 -> client credentials rotated; network text -> egress/proxy; 404 on GHES -> no device flow
} Prevention
- Allow egress to github.com/login/* (not just api.github.com) in firewalled environments
- Rotate and deploy client secrets atomically with the config referencing them
- On GHES, verify device-flow support before offering it as the fallback auth path
When it happens
Trigger: oc.DeviceAuth(ctx) at internal/oauth/flow.go:164 errors: POST to https://github.com/login/device/code returns 401/403 (bad client_id/secret), the device endpoint is blocked by a firewall/proxy, GHES older than the device-flow support returns 404, or the 30s timeout expires on a stalled connection.
Common situations: Firewalled environments blocking github.com login endpoints while allowing api.github.com; OAuth app client secret rotated but the server config still has the old one; GHES pre-3.x without device flow; PKCE was unavailable (headless, random port) and device flow is the sole remaining path, so its failure surfaces directly.
Related errors
- starting callback listener on %s: %w
- authentication required: set GITHUB_PERSONAL_ACCESS_TOKEN, c
- building installation token URL: %w
- requesting installation token: %w
- decoding installation token response: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/4bec1332a56a6c2f.
Report an issue: GitHub.