charmbracelet/crush · info
github copilot not available
Error message
github copilot not available
What it means
ErrNotAvailable signals that GitHub Copilot OAuth is not available in this build or context. loginCopilot and getCopilotToken return it as a sentinel error instead of attempting the OAuth device flow. Callers should compare with errors.Is and skip or fall back to another provider.
Source
Thrown at internal/oauth/copilot/oauth.go:25
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
"github.com/charmbracelet/crush/internal/oauth"
)
const (
clientID = "Iv1.b507a08c87ecfe98"
deviceCodeURL = "https://github.com/login/device/code"
accessTokenURL = "https://github.com/login/oauth/access_token"
copilotTokenURL = "https://api.github.com/copilot_internal/v2/token"
)
var ErrNotAvailable = errors.New("github copilot not available")
type DeviceCode struct {
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationURI string `json:"verification_uri"`
ExpiresIn int `json:"expires_in"`
Interval int `json:"interval"`
}
// RequestDeviceCode initiates the device code flow with GitHub.
func RequestDeviceCode(ctx context.Context) (*DeviceCode, error) {
data := url.Values{}
data.Set("client_id", clientID)
data.Set("scope", "read:user")
req, err := http.NewRequestWithContext(ctx, "POST", deviceCodeURL, strings.NewReader(data.Encode()))
if err != nil {
return nil, errView on GitHub (pinned to 7944b8e522)
Solutions
- Check for the sentinel with errors.Is(err, copilot.ErrNotAvailable) and treat it as 'provider unavailable', not a hard failure.
- Fall back to a different provider or prompt the user to pick another auth method.
- Verify the build/context actually supports Copilot OAuth before calling loginCopilot.
Example fix
// before
token, err := copilot.GetToken(ctx)
if err != nil { return err }
// after
token, err := copilot.GetToken(ctx)
if errors.Is(err, copilot.ErrNotAvailable) {
return ErrCopilotUnsupported // degrade gracefully
}
if err != nil { return err } Defensive patterns
Strategy: fallback
Validate before calling
if copilotErr := tryCopilotLogin(); errors.Is(copilotErr, copilot.ErrNotAvailable) { /* provider disabled */ } Type guard
func isCopilotUnavailable(err error) bool { return errors.Is(err, copilot.ErrNotAvailable) } Try / catch
token, err := loginCopilot(ctx)
if errors.Is(err, copilot.ErrNotAvailable) {
return fallbackProviderLogin(ctx)
}
if err != nil { return err } Prevention
- Always compare against the sentinel with errors.Is, not string matching.
- Have a non-Copilot provider configured as a fallback.
- Check provider availability before offering Copilot in the UI.
When it happens
Trigger: Calling loginCopilot or getCopilotToken when the Copilot provider is disabled/unavailable (e.g. no Copilot subscription or the feature is stubbed out in the build).
Common situations: Users select GitHub Copilot as a provider in crush but the Copilot integration is unavailable; scripts automating provider login hit this sentinel and must fall back to another auth path.
Related errors
- ${ErrorDescription}
- interactive OAuth authorization required
- failed to start OAuth callback listener: all candidate ports
- OAuth callback listener closed
- question cancelled by user
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/744eeb602e686d60.
Report an issue: GitHub.