mislav/hub · error

%s\n%s

Error message

%s\n%s

What it means

This is the tail of the HTTP error formatter (FormatError). After assembling the base error string (and any errorMessage from the response), it appends, on separate lines (%s\n%s), either a GitHub SSO authorization challenge or an insufficient-OAuth-scopes warning when those validators detect them. The two-line message means the request failed AND the response carried an SSO or scope signal.

Source

Thrown at github/client.go:1259

			errorSentences = append(errorSentences, fmt.Sprintf("Not allowed to change field \"%s\"", err.Field))
		}
	}

	var errorMessage string
	if len(errorSentences) > 0 {
		errorMessage = strings.Join(errorSentences, "\n")
	} 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

View on GitHub (pinned to 5c547ed804)

Solutions

  1. Follow the SSO authorization URL printed in the message (or in the X-Github-Sso header) to authorize your token for the organization.
  2. Regenerate the token with the required scopes (repo, read:org, workflow as needed) if a scope warning is appended.
  3. For fine-grained tokens, grant the token access to the specific organization/repository.
  4. Update the stored token (e.g. `gh auth login` or re-run the library's auth flow) after changing scopes.
Defensive patterns

Strategy: try-catch

Validate before calling

req, _ := http.NewRequest("GET", "https://api.github.com/user", nil)
req.Header.Set("Authorization", "Bearer "+token)
res, _ := http.DefaultClient.Do(req)
if sso := res.Header.Get("X-Github-Sso"); strings.HasPrefix(sso, "required; url=") {
    return fmt.Errorf("authorize token at %s", sso[strings.IndexByte(sso,'=')+1:])
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "authorize your token") || strings.Contains(err.Error(), "OAuth") {
        return fmt.Errorf("token needs SSO authorization or more scopes: %w", err)
    }
}

Prevention

When it happens

Trigger: Any REST call whose response triggers ValidateGitHubSSO (X-Github-Sso header present) or ValidateSufficientOAuthScopes (404/403 with scope mismatch), with errStr already containing the base HTTP error from the response errors.

Common situations: Accessing an org resource with a token not SSO-authorized for that org (common after enabling SAML SSO); using a classic PAT whose scopes (repo, read:org) don't cover the requested resource; enterprise deployments requiring fine-grained permissions.

Related errors


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