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.

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.

Appendix: 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)