mislav/hub · error

%s

Error message

%s

What it means

When an HTTP API request fails (e.g. a 4xx/5xx response), hub builds an errStr from the response and then calls ValidateSufficientOAuthScopes on the response. If the response indicates the token lacks required OAuth scopes (via the X-Accepted-OAuth-Scopes / X-OAuth-Scopes headers), the scope-validation error is appended to the original error message with fmt.Errorf("%s\n%s"). This means the thrown error is a compound: the API failure plus a hint that your token's scopes are insufficient.

Source

Thrown at github/client.go:1266

	} else {
		errorMessage = e.Message
		if action == "getting current user" && e.Message == "Resource not accessible by integration" {
			errorMessage = errorMessage + "\nYou must specify GITHUB_USER via environment variable."
		}
	}
	if errorMessage != "" {
		errStr = fmt.Sprintf("%s\n%s", errStr, errorMessage)
	}

	if ssoErr := ValidateGitHubSSO(e.Response); ssoErr != nil {
		return fmt.Errorf("%s\n%s", errStr, ssoErr)
	}

	if scopeErr := ValidateSufficientOAuthScopes(e.Response); scopeErr != nil {
		return fmt.Errorf("%s\n%s", errStr, scopeErr)
	}

	return errors.New(errStr)
}

// ValidateGitHubSSO checks for the challenge via `X-Github-Sso` header
func ValidateGitHubSSO(res *http.Response) error {
	if res.StatusCode != 403 {
		return nil
	}

	sso := res.Header.Get("X-Github-Sso")
	if !strings.HasPrefix(sso, "required; url=") {
		return nil
	}

	url := sso[strings.IndexByte(sso, '=')+1:]
	return fmt.Errorf("You must authorize your token to access this organization:\n%s", url)
}

// ValidateSufficientOAuthScopes warns about insufficient OAuth scopes

View on GitHub (pinned to 5c547ed804)

Solutions

  1. Regenerate or edit your GitHub token to include the required scopes (typically 'repo', plus 'gist' or 'read:org' as needed) and update it via `hub config` or $GITHUB_TOKEN.
  2. Read the second line of the error: it names the required vs. accepted scopes from the response headers; grant exactly those.
  3. If using SSO, authorize the token for the organization (see the X-Github-SSO header handling in the same file).
  4. Verify with `curl -H "Authorization: token $TOKEN" https://api.github.com/user` and inspect the X-OAuth-Scopes header.

Example fix

// before: token with no scopes
export GITHUB_TOKEN=ghp_minimal_token
// after: create token with repo, read:org, gist scopes
export GITHUB_TOKEN=ghp_token_with_repo_readorg_gist_scopes
Defensive patterns

Strategy: validation

Validate before calling

// Before calls that need scopes, verify the token's scopes:
resp, _ := http.Get("https://api.github.com/user") // with Authorization header
scopes := resp.Header.Get("X-OAuth-Scopes")
if !strings.Contains(scopes, "repo") {
    return fmt.Errorf("token lacks 'repo' scope; has: %s", scopes)
}

Type guard

func hasScope(header string, want string) bool {
    for _, s := range strings.Split(header, ", ") {
        if s == want { return true }
    }
    return false
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "OAuth scopes") {
        // prompt user to regenerate token with required scopes
    }
    return err
}

Prevention

When it happens

Trigger: Any failing GitHub API call made with a token whose scopes don't include what the endpoint requires (e.g. a token without 'repo' scope accessing a private repository, or missing 'gist'/'read:org' scopes) where the response status is also an error.

Common situations: Using a fine-grained or classic PAT created with minimal scopes; GITHUB_TOKEN from CI with restricted permissions; token scopes changed/revoked after hub was configured; enterprise instances with different default scopes.

Related errors


AI-assisted analysis of mislav/hub@5c547ed804 (2026-09-01). Data as JSON: /api/errors/699255bc3efd2a07. Report an issue: GitHub.