github/github-mcp-server · error
failed to get user permission level: %w
Error message
failed to get user permission level: %w
What it means
checkPushAccess calls the REST endpoint GET /repos/{owner}/{repo}/collaborators/{username}/permission to decide push access. GitHub returns 404 when the queried user is not a collaborator at all, and 403 when the caller's token lacks the collaborators permission (typical for fine-grained PATs or app tokens without it), so lockdown checks on outside contributors or least-privilege tokens surface as this wrapped error. Only admin/write count as push access.
Source
Thrown at pkg/lockdown/lockdown.go:280
if err := c.client.Query(ctx, &query, variables); err != nil {
return false, "", fmt.Errorf("failed to query repository metadata: %w", err)
}
c.logDebug(ctx, fmt.Sprintf("queried repo access info for %s/%s: isPrivate=%t", owner, repo, bool(query.Repository.IsPrivate)))
return bool(query.Repository.IsPrivate), string(query.Viewer.Login), nil
}
// checkPushAccess checks if the user has push access to the repository via the REST permission endpoint.
func (c *RepoAccessCache) checkPushAccess(ctx context.Context, username, owner, repo string) (bool, error) {
if c.restClient == nil {
return false, fmt.Errorf("nil REST client")
}
permLevel, _, err := c.restClient.Repositories.GetPermissionLevel(ctx, owner, repo, username)
if err != nil {
return false, fmt.Errorf("failed to get user permission level: %w", err)
}
// REST API maps "maintain" to "write" (and "triage" to "read")
// https://docs.github.com/en/rest/collaborators/collaborators#get-repository-permissions-for-a-user
permission := permLevel.GetPermission()
return permission == "admin" || permission == "write", nil
}
func (c *RepoAccessCache) log(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr) {
if c == nil || c.logger == nil {
return
}
if !c.logger.Enabled(ctx, level) {
return
}
c.logger.LogAttrs(ctx, level, msg, attrs...)
}
View on GitHub (pinned to 0ea1f775a7)
Solutions
- Map a 404-wrapped failure to hasPushAccess=false instead of an error - outside users are an expected case
- Give the token collaborator read access: classic PAT needs repo scope; fine-grained PAT needs repository 'Collaborators: read'
- For GitHub Apps, request the collaborators read permission on the installation
- Authorize the token for SAML-protected organizations when applicable
Defensive patterns
Strategy: try-catch
Try / catch
if _, err := cache.IsSafeContent(ctx, username, owner, repo); err != nil {
var ghErr *github.ErrorResponse
if errors.As(err, &ghErr) && ghErr.Response != nil && ghErr.Response.StatusCode == http.StatusNotFound {
// user is not a collaborator: that IS the answer (no push access), not a failure
ok, err = false, nil
}
} Prevention
- Grant the reading token 'Collaborators: read' so the permission endpoint is reachable
- Treat 404 from this endpoint as a normal 'no access' answer in lockdown logic
- Audit fine-grained PAT permission sets before enabling lockdown
When it happens
Trigger: Lockdown evaluating content authored by a user with no collaborator status on the repo (404); a fine-grained PAT without the repository 'Collaborators: read' permission (403); a GitHub App token missing the collaborators read permission; SAML-protected org with an unauthorized token.
Common situations: Public repos where outside contributors' content is checked; fine-grained PATs whose permission set skipped collaborator access in the name of least privilege.
Related errors
- %s: %w
- failed to query repository metadata: %w
- unexpected status %d: %s
- failed to get job logs for job %d: %w
- failed to update issue with agent assignment: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/5d781905eaa4781e.
Report an issue: GitHub.