sipeed/picoclaw · error
failed to query WeCom QR result: %w
Error message
failed to query WeCom QR result: %w
What it means
A single poll iteration failed at the HTTP layer: doWeComJSONGet returned an error while GETting the query URL. This wraps transport failures, non-200 statuses ('unexpected status 502 Bad Gateway...'), and body decode failures ('decode JSON response...'). Unlike DeadlineExceeded, any other error here aborts the whole login immediately — one transient 502 kills the flow.
Source
Thrown at cmd/picoclaw/internal/auth/wecom.go:334
case <-timeoutCtx.Done():
if errors.Is(timeoutCtx.Err(), context.DeadlineExceeded) {
return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan timed out after %s", opts.PollTimeout)
}
return wecomQRBotInfo{}, timeoutCtx.Err()
case <-time.After(opts.PollInterval):
}
}
}
func queryWeComQRCodeStatus(ctx context.Context, opts wecomQRFlowOptions, scode string) (wecomQRQueryResponse, error) {
queryURL, err := buildWeComQRQueryURL(opts.QueryURL, scode)
if err != nil {
return wecomQRQueryResponse{}, err
}
var resp wecomQRQueryResponse
if err := doWeComJSONGet(ctx, opts.HTTPClient, queryURL, &resp); err != nil {
return wecomQRQueryResponse{}, fmt.Errorf("failed to query WeCom QR result: %w", err)
}
if resp.ErrCode != 0 {
return wecomQRQueryResponse{}, fmt.Errorf(
"failed to query WeCom QR result: errcode=%d errmsg=%s",
resp.ErrCode,
resp.ErrMsg,
)
}
return resp, nil
}
func buildWeComQRGenerateURL(baseURL, sourceID string, platformCode int) (string, error) {
u, err := url.Parse(baseURL)
if err != nil {
return "", fmt.Errorf("invalid WeCom QR generate URL: %w", err)
}
View on GitHub (pinned to 49183d7e8d)
Solutions
- Check whether the failure is persistent (curl the query endpoint) or was a one-off, then simply retry the login
- Stabilize network/VPN before starting an interactive login
- Update picoclaw — newer builds may tolerate transient poll errors by continuing the loop
- If a proxy intercepts, bypass it for the WeCom relay domain
Example fix
// before
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
}
// after: tolerate isolated poll failures until the overall deadline
status, err := queryWeComQRCodeStatus(timeoutCtx, opts, scode)
if err != nil {
if errors.Is(timeoutCtx.Err(), context.DeadlineExceeded) {
return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan timed out after %s", opts.PollTimeout)
}
if !errors.Is(err, context.Canceled) {
select {
case <-timeoutCtx.Done():
return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan timed out after %s", opts.PollTimeout)
case <-time.After(opts.PollInterval):
continue
}
}
return wecomQRBotInfo{}, err
} Defensive patterns
Strategy: retry
Type guard
func isTransientPollErr(err error) bool {
var netErr net.Error
if errors.As(err, &netErr) { return true }
return strings.Contains(err.Error(), "unexpected status 50") ||
strings.Contains(err.Error(), "unexpected status 429")
} Try / catch
status, err := queryWeComQRCodeStatus(timeoutCtx, opts, scode)
if err != nil && isTransientPollErr(err) && timeoutCtx.Err() == nil {
select {
case <-timeoutCtx.Done():
return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan timed out after %s", opts.PollTimeout)
case <-time.After(opts.PollInterval):
continue
}
} Prevention
- Treat single poll failures as retryable until the overall deadline
- Only abort immediately on context.Canceled or persistent errors
When it happens
Trigger: A single 502/503 from a load balancer between polls; TLS reset mid-request; response body was HTML (proxy error page) so JSON decode failed; HTTP timeout on one poll exceeding wecomQRHTTPTimeout.
Common situations: Relay behind a flaky CDN; momentary network switch (Wi-Fi to VPN); captive portal intercepting mid-flow; relay rolling deploy causing one 502.
Related errors
- failed to get WeCom QR code: %w
- WeCom QR scan timed out after %s
- failed to query WeCom QR result: errcode=%d errmsg=%s
- unexpected status %s
- decode JSON response: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/b4bb18e0e42e9217.
Report an issue: GitHub.