github/github-mcp-server · error · ErrStaleAuthorizationFlow
authorization prompt has expired
Error message
authorization prompt has expired
What it means
First guard of validateBlamePath, run by get_file_blame before any network call: strings.TrimSpace(path) == "" is rejected. The GraphQL blame query needs a concrete file path; an empty or all-whitespace path would either fail at GitHub or match nothing, so the server refuses it locally with 'path must not be empty'.
Source
Thrown at internal/oauth/manager.go:26
"net/http"
"os"
"sync"
"time"
"golang.org/x/oauth2"
)
// DefaultAuthTimeout bounds how long a single authorization attempt waits for
// the user to complete the browser or device flow.
const DefaultAuthTimeout = 5 * time.Minute
// tokenRefreshTimeout bounds each background refresh of an expiring token so a
// stalled GitHub token endpoint cannot block a tool call indefinitely.
const tokenRefreshTimeout = 30 * time.Second
// ErrStaleAuthorizationFlow indicates that a prompt response belongs to an
// authorization flow that is no longer current.
var ErrStaleAuthorizationFlow = errors.New("authorization prompt has expired")
// flowStatus tracks the manager's single-flight authorization state.
type flowStatus int
const (
statusIdle flowStatus = iota // no flow running
statusStarting // a flow is being prepared (brief)
statusInProgress // a flow is running on a secure channel; callers may join
statusAwaitingUser // a flow is running but the user must act out-of-band
)
// Outcome reports the result of an authorization attempt that did not
// immediately yield a token.
type Outcome struct {
// UserAction, when non-nil, must be surfaced to the user. The authorization
// flow continues in the background; the user should retry once they have
// completed it.
UserAction *UserActionView on GitHub (pinned to 0ea1f775a7)
Solutions
- Pass a real repository-relative file path such as "src/main.go"
- If the path comes from a variable, default it and skip the call when blank rather than sending whitespace
- Trim inputs before invoking the tool to catch the mistake client-side
Example fix
// before
{"owner":"octocat","repo":"Hello-World","path":" "}
// after
{"owner":"octocat","repo":"Hello-World","path":"README.md"} Defensive patterns
Strategy: validation
Validate before calling
func validBlamePathPresence(p string) bool {
return strings.TrimSpace(p) != ""
} Type guard
func isBlamePathError(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "path must")
} Try / catch
if strings.TrimSpace(path) == "" {
// skip or fetch a default file instead of calling with a blank path
return nil, fmt.Errorf("no file path provided")
}
res, _, err := callGetFileBlame(ctx, buildArgs(owner, repo, path))
if isBlamePathError(err) {
return nil, fmt.Errorf("fix the path argument: %w", err)
} Prevention
- Make path a required field in calling code, not an optional default
- Skip blank entries when iterating file lists
- Trim inputs before invoking the tool
- Fail fast client-side - the server only re-rejects what you could have checked
When it happens
Trigger: Omitting the path argument so it defaults to ""; passing a whitespace-only string (spaces/tabs/newlines); templating bugs that interpolate an unset variable into path.
Common situations: LLM tool calls that drop a required parameter; CI scripts iterating a file list where one entry is blank; config-driven blame jobs with an empty template slot.
Related errors
- authorization did not complete
- response did not include the deleted project view
- provide either 'visible_fields' or 'visible_field_names', no
- installation token response did not contain a token
- installation token response did not contain an expiry
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/4a25a63f85db0375.
Report an issue: GitHub.