chenhg5/cc-connect · error

onboarding session expired

Error message

onboarding session expired

What it means

The device-code onboarding session expired before the user completed authorization: the poll response carried error=expired_token. Device codes have a server-defined lifetime; if the QR is not scanned and approved in time, the session can no longer be completed and the flow aborts.

Source

Thrown at cmd/cc-connect/feishu.go:631

		}

		if pollRes.ClientID != "" && pollRes.ClientSecret != "" {
			return &registrationFlowResult{
				AppID:       pollRes.ClientID,
				AppSecret:   pollRes.ClientSecret,
				OwnerOpenID: pollRes.UserInfo.OpenID,
				Platform:    platformType,
			}, nil
		}

		switch pollRes.Error {
		case "", "authorization_pending":
		case "slow_down":
			interval += 5
		case "access_denied":
			return nil, fmt.Errorf("authorization denied by user")
		case "expired_token":
			return nil, fmt.Errorf("onboarding session expired")
		default:
			if pollRes.Error != "" {
				return nil, fmt.Errorf("%s: %s", pollRes.Error, pollRes.ErrorDescription)
			}
		}

		time.Sleep(time.Duration(interval) * time.Second)
	}

	return nil, fmt.Errorf("timed out waiting for QR onboarding result")
}

func (c *registrationClient) registrationCall(action string, params map[string]string, out any) error {
	form := url.Values{}
	form.Set("action", action)
	for k, v := range params {
		form.Set(k, v)
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Re-run the setup command to get a fresh QR code and scan it promptly.
  2. Scan the QR soon after it appears — treat the code as short-lived.
  3. If you keep hitting slow_down/expiry, do not slow the loop further; restart the flow rather than continue polling an aging session.
  4. Check clock skew on the machine — a wildly wrong local clock can distort the local timeout loop.

Example fix

// before
// QR left >10 min → onboarding session expired
// after
$ cc-connect setup feishu   # scan the new QR within a minute or two
Defensive patterns

Strategy: retry

Try / catch

if err := runRegistrationFlow(...); err != nil {
	if strings.Contains(err.Error(), "onboarding session expired") {
		fmt.Println("QR expired. Re-running setup for a fresh code...")
		return runRegistrationFlow(...) // one fresh attempt
	}
	return err
}

Prevention

When it happens

Trigger: The polling loop receives pollRes.Error == "expired_token" — the user waited too long to scan/approve, or the interval/slow-down handling stretched the loop past the server's device-code expiry.

Common situations: QR code left on screen for many minutes while the user fetched their phone; repeated slow_down responses pushing the effective wait past expiry; user abandoning the flow and returning later to the same stale QR.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/062ac702d4194ee8. Report an issue: GitHub.