router-for-me/CLIProxyAPI · warning
kimi: context cancelled: %w
Error message
kimi: context cancelled: %w
What it means
The polling loop in PollForToken detected that its context was cancelled (or its deadline exceeded) while waiting for the user to complete authorization. The wrapped ctx.Err() is context.Canceled or context.DeadlineExceeded. No token was obtained; the device code itself may still be valid until it expires server-side.
Source
Thrown at internal/auth/kimi/kimi.go:247
if interval < defaultPollInterval {
interval = defaultPollInterval
}
deadline := time.Now().Add(maxPollDuration)
if deviceCode.ExpiresIn > 0 {
codeDeadline := time.Now().Add(time.Duration(deviceCode.ExpiresIn) * time.Second)
if codeDeadline.Before(deadline) {
deadline = codeDeadline
}
}
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return nil, fmt.Errorf("kimi: context cancelled: %w", ctx.Err())
case <-ticker.C:
if time.Now().After(deadline) {
return nil, fmt.Errorf("kimi: device code expired")
}
token, pollErr, shouldContinue := c.exchangeDeviceCode(ctx, deviceCode.DeviceCode)
if token != nil {
return token, nil
}
if !shouldContinue {
return nil, pollErr
}
// Continue polling
}
}
}
// exchangeDeviceCode attempts to exchange the device code for an access token.View on GitHub (pinned to 78f0c4079e)
Solutions
- If the user cancelled intentionally, no fix needed — re-run login to start a fresh device flow
- If DeadlineExceeded, give the context passed to PollForToken a deadline >= deviceCode.ExpiresIn (or the 15-minute maxPollDuration)
- Ensure the ctx passed to WaitForAuthorization is not derived from a short-lived request scope; use a dedicated context for interactive login
Example fix
// before ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // too short for user to authorize k.WaitForAuthorization(ctx, deviceCode) // after ctx, cancel := context.WithCancel(context.Background()) defer cancel() // cancel only on user interrupt k.WaitForAuthorization(ctx, deviceCode)
Defensive patterns
Strategy: validation
Validate before calling
// Give interactive login its own long-lived context before polling
if _, ok := ctx.Deadline(); !ok {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, 16*time.Minute)
defer cancel()
} Try / catch
if err != nil && errors.Is(err, context.Canceled) {
// user aborted: clean up UI state, do not report as a bug
} Prevention
- Never derive the login context from short-deadline request scopes
- Cancel only on user intent (Ctrl-C), not timers
- Distinguish Canceled vs DeadlineExceeded in handling
When it happens
Trigger: Caller of WaitForAuthorization/PollForToken cancels the ctx (user hits Ctrl-C during the 'visit this URL' wait), a parent context with a deadline shorter than the 15-minute maxPollDuration, server shutdown while a login is in progress.
Common situations: CLI login command with its own timeout shorter than user takes to authorize, TUI/manager cancelling in-flight logins on restart, context propagated from an HTTP request that times out.
Related errors
- kimi: failed to create device code request: %w
- kimi: device code request failed: %w
- kimi: failed to read device code response: %w
- kimi: device code request failed with status %d: %s
- kimi: failed to parse device code response: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/a2d32bc1a68dda6c.
Report an issue: GitHub.