sipeed/picoclaw · error

failed to get WeCom QR code: %w

Error message

failed to get WeCom QR code: %w

What it means

The initial HTTP GET to the WeCom QR generate endpoint failed at the transport layer inside doWeComJSONGet (client.Do returned an error). This is pure connectivity — DNS resolution, TCP connect, TLS handshake, or the per-request HTTP timeout (wecomQRHTTPTimeout on the client built in defaultWeComQRFlowOptions) — before any status code was received.

Source

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

	if opts.PollTimeout <= 0 {
		opts.PollTimeout = wecomQRPollTimeout
	}
	if opts.Writer == nil {
		opts.Writer = os.Stdout
	}

	return opts
}

func fetchWeComQRCode(ctx context.Context, opts wecomQRFlowOptions) (wecomQRSession, error) {
	generateURL, err := buildWeComQRGenerateURL(opts.GenerateURL, opts.SourceID, wecomPlatformCode())
	if err != nil {
		return wecomQRSession{}, err
	}

	var resp wecomQRGenerateResponse
	if err := doWeComJSONGet(ctx, opts.HTTPClient, generateURL, &resp); err != nil {
		return wecomQRSession{}, fmt.Errorf("failed to get WeCom QR code: %w", err)
	}
	if resp.ErrCode != 0 {
		return wecomQRSession{}, fmt.Errorf(
			"failed to get WeCom QR code: errcode=%d errmsg=%s",
			resp.ErrCode,
			resp.ErrMsg,
		)
	}
	if resp.Data.SCode == "" || resp.Data.AuthURL == "" {
		return wecomQRSession{}, fmt.Errorf("failed to get WeCom QR code: response missing scode or auth_url")
	}

	return wecomQRSession{
		SCode:   resp.Data.SCode,
		AuthURL: resp.Data.AuthURL,
	}, nil
}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Check basic connectivity: curl -v the generate endpoint URL and look for DNS/TLS/connect errors
  2. Fix or disable HTTP(S)_PROXY env vars if a corporate proxy interferes
  3. Retry after a moment — transient relay outages are common
  4. Update picoclaw in case the relay endpoint URL changed between versions
  5. Verify system clock is correct (TLS cert validation depends on it)

Example fix

// before
if err := doWeComJSONGet(ctx, opts.HTTPClient, generateURL, &resp); err != nil {
	return wecomQRSession{}, fmt.Errorf("failed to get WeCom QR code: %w", err)
}

// after: retry once on transport errors, since QR relay blips are transient
var resp wecomQRGenerateResponse
err := doWeComJSONGet(ctx, opts.HTTPClient, generateURL, &resp)
if err != nil {
	time.Sleep(2 * time.Second)
	err = doWeComJSONGet(ctx, opts.HTTPClient, generateURL, &resp)
}
if err != nil {
	return wecomQRSession{}, fmt.Errorf("failed to get WeCom QR code: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

// Cheap connectivity pre-flight before an interactive flow
if _, err := net.DialTimeout("tcp", relayHostPort, 3*time.Second); err != nil {
	return fmt.Errorf("cannot reach WeCom QR relay: %w", err)
}

Type guard

func isTransportErr(err error) bool {
	var netErr net.Error
	return errors.As(err, &netErr) || errors.Is(err, io.EOF)
}

Try / catch

var resp wecomQRGenerateResponse
err := doWeComJSONGet(ctx, opts.HTTPClient, generateURL, &resp)
if err != nil && isTransportErr(err) {
	time.Sleep(2 * time.Second)
	err = doWeComJSONGet(ctx, opts.HTTPClient, generateURL, &resp)
}
if err != nil {
	return wecomQRSession{}, fmt.Errorf("failed to get WeCom QR code: %w", err)
}

Prevention

When it happens

Trigger: No internet or DNS failure when starting picoclaw's WeCom login; the QR relay service host unreachable; a proxy or firewall blocking the generate URL; TLS interception by a corporate proxy whose CA is not trusted; HTTP client timeout exceeded before the server responded.

Common situations: Running login inside a container without network; corporate egress proxy blocking the endpoint; the QR relay endpoint is temporarily down; system clock skew breaking TLS.

Related errors


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