sipeed/picoclaw · error

failed to get WeCom QR code: errcode=%d errmsg=%s

Error message

failed to get WeCom QR code: errcode=%d errmsg=%s

What it means

The WeCom QR generate service answered HTTP 200 but with a business-level error: the response JSON carried a non-zero errcode field with errmsg. This is the relay/application layer rejecting the request — distinct from transport errors — and includes the numeric code and server message verbatim in the error string.

Source

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

	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
}

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

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Decode errcode: 4xx-style codes usually mean bad request params (update picoclaw), 5xx-style codes mean relay trouble (retry later)
  2. Update picoclaw so the sourceID/plat parameters match what the relay currently accepts
  3. Wait ~1 minute and retry if the code suggests throttling
  4. Report the errcode/errmsg pair to the picoclaw maintainers if it persists on the latest version
Defensive patterns

Strategy: try-catch

Type guard

func isWeComErrCode(err error) (code int, ok bool) {
	var e wecomErr
	if errors.As(err, &e) { return e.code, true }
	return 0, false
}

Try / catch

if resp.ErrCode != 0 {
	if isThrottleCode(resp.ErrCode) {
		time.Sleep(30 * time.Second)
		// retry generate once
	}
	return wecomQRSession{}, fmt.Errorf("failed to get WeCom QR code: errcode=%d errmsg=%s", resp.ErrCode, resp.ErrMsg)
}

Prevention

When it happens

Trigger: The relay rejects the source/sourceID query parameters (invalid or blocked client source); rate limiting on the QR generate endpoint; relay-side outage returning errcode!=0; plat code parameter rejected for the detected platform.

Common situations: The login relay temporarily throttles burst logins; picoclaw version uses an outdated sourceID the relay no longer accepts; server-side incident returning generic errcode 500-style responses.

Related errors


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