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
- Re-run the login command and scan promptly — the QR is single-use and time-boxed
- Open the printed QR Code Link URL directly on the phone if the terminal QR will not scan
- Pass a larger timeout to the WeCom login flow if the default is too short for your users
- 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
- Size PollTimeout to real user behavior (scan + confirm) — 2+ minutes minimum
- Instruct users to keep their phone ready before starting login
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- failed to query WeCom QR result: %w
- failed to query WeCom QR result: errcode=%d errmsg=%s
- failed to load config: %w
- failed to save config: %w
- failed to get WeCom QR code: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/c0158d335378baf5.
Report an issue: GitHub.