sipeed/picoclaw · error

failed to get WeCom QR code: response missing scode or auth_

Error message

failed to get WeCom QR code: response missing scode or auth_url

What it means

The generate endpoint returned errcode 0 (success) but the data payload lacked scode or auth_url, the two fields the QR session needs. This is a contract violation by the relay: the response parsed as JSON and claimed success, yet the session fields are empty strings.

Source

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

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")
	}

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

	var scannedPrinted bool

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Update picoclaw to the latest version to match the current relay response schema
  2. Inspect the raw response with curl to confirm the relay is sending scode and auth_url
  3. Retry after a short wait in case of relay degradation
  4. If the relay schema truly changed, pin the compatible picoclaw release or report the break upstream
Defensive patterns

Strategy: validation

Validate before calling

// Treat an empty session payload as retryable instead of hard-failing
if resp.Data.SCode == "" || resp.Data.AuthURL == "" {
	// retry generate once before giving up
}

Type guard

func hasQRSession(resp wecomQRGenerateResponse) bool {
	return resp.ErrCode == 0 && resp.Data.SCode != "" && resp.Data.AuthURL != ""
}

Prevention

When it happens

Trigger: Relay API version drift where field names change (e.g. scode renamed); relay degraded and returning a success envelope with empty data; an interception proxy returning a stubbed JSON body with matching outer shape.

Common situations: picoclaw binary older than a relay-side response schema change; transparent proxy injecting its own JSON; relay partial outage.

Related errors


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