router-for-me/CLIProxyAPI · error

xai device code: response is nil

Error message

xai device code: response is nil

What it means

PollForToken was called with a nil *DeviceCodeResponse. This is a programming-contract violation, not a server condition: the poll loop needs deviceCode.DeviceCode and deviceCode.TokenEndpoint, so it fails fast instead of panicking on a nil dereference.

Source

Thrown at internal/auth/xai/xai.go:199

	if err != nil {
		return nil, err
	}
	tokenEndpoint := ""
	if deviceCode != nil {
		tokenEndpoint = strings.TrimSpace(deviceCode.TokenEndpoint)
	}
	return &AuthBundle{
		TokenData:     *tokenData,
		LastRefresh:   time.Now().UTC().Format(time.RFC3339),
		BaseURL:       DefaultAPIBaseURL,
		TokenEndpoint: tokenEndpoint,
	}, nil
}

// PollForToken polls the token endpoint until the user authorizes or the device code expires.
func (a *XAIAuth) PollForToken(ctx context.Context, deviceCode *DeviceCodeResponse) (*TokenData, error) {
	if deviceCode == nil {
		return nil, fmt.Errorf("xai device code: response is nil")
	}
	if ctx == nil {
		ctx = context.Background()
	}

	tokenEndpoint := strings.TrimSpace(deviceCode.TokenEndpoint)
	if tokenEndpoint == "" {
		discovery, errDiscover := a.Discover(ctx)
		if errDiscover != nil {
			return nil, errDiscover
		}
		tokenEndpoint = discovery.TokenEndpoint
	}

	interval := time.Duration(deviceCode.Interval) * time.Second
	if interval < defaultPollInterval {
		interval = defaultPollInterval
	}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Audit the call site: ensure RequestDeviceCode's error is checked before using its result (idiomatic `if err != nil { return err }` before PollForToken)
  2. Initialize the pointer only on success paths and never share nilable states across goroutines
  3. Keep using WaitForAuthorization, which chains RequestDeviceCode and PollForToken safely

Example fix

// before
deviceCode, _ := auth.RequestDeviceCode(ctx)
auth.PollForToken(ctx, deviceCode) // panics guard: nil

// after
deviceCode, err := auth.RequestDeviceCode(ctx)
if err != nil {
    return err
}
auth.PollForToken(ctx, deviceCode)
Defensive patterns

Strategy: validation

Validate before calling

deviceCode, err := auth.RequestDeviceCode(ctx)
if err != nil {
    return err
}
if deviceCode == nil {
    return fmt.Errorf("device code response unexpectedly nil")
}

Prevention

When it happens

Trigger: Calling XAIAuth.PollForToken(ctx, nil) directly, or a caller passing a nil pointer returned from a failed RequestDeviceCode whose error was ignored.

Common situations: Caller ignores the error from RequestDeviceCode and passes the resulting nil bundle onward; refactor that made DeviceCodeResponse optional without updating this path; race where the device code is cleared before polling starts.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/1ad7c65f255f5014. Report an issue: GitHub.