sipeed/picoclaw · error

invalid WeCom QR query URL: %w

Error message

invalid WeCom QR query URL: %w

What it means

url.Parse rejected opts.QueryURL inside buildWeComQRQueryURL, which is called on every poll iteration. Same class as error 133 but for the status-query endpoint: the configured base URL is unparseable (control characters, invalid escapes), which in practice only happens with a custom/injected QueryURL rather than the wecomQRQueryEndpoint default.

Source

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

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

	query := u.Query()
	query.Set("source", sourceID)
	query.Set("sourceID", sourceID)
	query.Set("plat", strconv.Itoa(platformCode))
	u.RawQuery = query.Encode()

	return u.String(), nil
}

func buildWeComQRQueryURL(baseURL, scode string) (string, error) {
	u, err := url.Parse(baseURL)
	if err != nil {
		return "", fmt.Errorf("invalid WeCom QR query URL: %w", err)
	}

	query := u.Query()
	query.Set("scode", scode)
	u.RawQuery = query.Encode()

	return u.String(), nil
}

func buildWeComQRCodePageURL(baseURL, sourceID, scode string) (string, error) {
	u, err := url.Parse(baseURL)
	if err != nil {
		return "", fmt.Errorf("invalid WeCom QR page URL: %w", err)
	}

	query := u.Query()
	query.Set("source", sourceID)
	query.Set("sourceID", sourceID)

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Validate the QueryURL override once before the flow starts (see validation example)
  2. Use the default relay unless a custom one is required
  3. Trim whitespace and remove quotes/newlines from any URL sourced from env/config
  4. Log the offending value at configuration time so the failure is obvious

Example fix

// before
queryURL, err := buildWeComQRQueryURL(opts.QueryURL, scode)

// after: preflight once in the caller
if _, err := url.Parse(opts.QueryURL); err != nil {
	return fmt.Errorf("invalid QueryURL %q: %w", opts.QueryURL, err)
}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := url.Parse(opts.QueryURL); err != nil {
	return fmt.Errorf("QueryURL %q is not a valid URL: %w", opts.QueryURL, err)
}

Type guard

func isInvalidURL(err error) bool {
	return err != nil && strings.Contains(err.Error(), "invalid URL")
}

Prevention

When it happens

Trigger: Custom wecomQRFlowOptions with a malformed QueryURL; tests stubbing the query endpoint with a bad string; env/config override introducing trailing garbage onto the URL.

Common situations: Pointing picoclaw at a self-hosted WeCom QR relay with a typo; string-built URLs with unencoded inserts; stale override surviving from an experiment.

Related errors


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