sipeed/picoclaw · warning

WeCom QR scan timed out after %s

Error message

WeCom QR scan timed out after %s

What it means

The WeCom QR polling loop aborted because the overall poll deadline (opts.PollTimeout, default wecomQRPollTimeout) was exceeded while queryWeComQRCodeStatus kept returning errors — specifically the error itself or the derived timeoutCtx was DeadlineExceeded. The message includes the configured duration, e.g. 'WeCom QR scan timed out after 2m0s'.

Source

Thrown at cmd/picoclaw/internal/auth/wecom.go:292

		AuthURL: resp.Data.AuthURL,
	}, nil
}

func pollWeComQRCodeResult(ctx context.Context, opts wecomQRFlowOptions, scode string) (wecomQRBotInfo, error) {
	if strings.TrimSpace(scode) == "" {
		return wecomQRBotInfo{}, fmt.Errorf("missing WeCom QR scode")
	}

	timeoutCtx, cancel := context.WithTimeout(ctx, opts.PollTimeout)
	defer cancel()

	var scannedPrinted bool

	for {
		status, err := queryWeComQRCodeStatus(timeoutCtx, opts, scode)
		if err != nil {
			if errors.Is(err, context.DeadlineExceeded) || errors.Is(timeoutCtx.Err(), context.DeadlineExceeded) {
				return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan timed out after %s", opts.PollTimeout)
			}
			return wecomQRBotInfo{}, err
		}

		switch strings.ToLower(status.Data.Status) {
		case "success":
			if status.Data.BotInfo.BotID == "" || status.Data.BotInfo.Secret == "" {
				return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan succeeded but bot credentials are missing")
			}
			return wecomQRBotInfo{
				BotID:  status.Data.BotInfo.BotID,
				Secret: status.Data.BotInfo.Secret,
			}, nil
		case "expired":
			return wecomQRBotInfo{}, fmt.Errorf("WeCom QR code expired, please retry")
		case "scaned", "scanned":
			if !scannedPrinted {
				fmt.Fprintln(opts.Writer, "QR code scanned. Confirm the login in WeCom.")

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Re-run the login command and scan promptly — the QR is single-use and time-boxed
  2. Open the printed QR Code Link URL directly on the phone if the terminal QR will not scan
  3. Pass a larger timeout to the WeCom login flow if the default is too short for your users
  4. Fix underlying network instability so individual polls succeed (see errors 131/137)
Defensive patterns

Strategy: retry

Validate before calling

// Pass an explicit, generous timeout for interactive use
opts := defaultWeComQRFlowOptions(5 * time.Minute)

Type guard

func isScanTimeout(err error) bool {
	return err != nil && strings.HasPrefix(err.Error(), "WeCom QR scan timed out")
}

Try / catch

info, err := pollWeComQRCodeResult(ctx, opts, session.SCode)
if isScanTimeout(err) {
	// prompt user and restart the whole generate+poll flow with a fresh QR
}

Prevention

When it happens

Trigger: User never scans the QR code before the poll timeout; each status query errored (network flaps) until the deadline; PollTimeout explicitly set very short via the flow options.

Common situations: User walked away from the terminal after starting login; phone cannot reach the QR page (region/network); flaky network making every poll fail until deadline.

Understand the failure class

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/c0158d335378baf5. Report an issue: GitHub.