sipeed/picoclaw · error

unexpected status %s: %s

Error message

unexpected status %s: %s

What it means

The WeCom HTTP GET returned a non-200 status with a readable body: the error is 'unexpected status <status>: <first 8KB of body>'. This is the primary non-OK diagnostic — e.g. '502 Bad Gateway: <html>...' from a relay behind a load balancer, or a 404 when the endpoint path moved. Because doWeComJSONGet is shared, this surfaces wrapped inside errors 124 and 131.

Source

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

func doWeComJSONGet(ctx context.Context, client *http.Client, targetURL string, out any) error {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, targetURL, nil)
	if err != nil {
		return err
	}

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, readErr := io.ReadAll(io.LimitReader(resp.Body, 8192))
		if readErr != nil {
			return fmt.Errorf("unexpected status %s", resp.Status)
		}
		return fmt.Errorf("unexpected status %s: %s", resp.Status, strings.TrimSpace(string(body)))
	}

	if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
		return fmt.Errorf("decode JSON response: %w", err)
	}

	return nil
}

func wecomPlatformCode() int {
	switch runtime.GOOS {
	case "darwin":
		return 1
	case "windows":
		return 2
	case "linux":
		return 3
	default:

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Read the embedded status and body: 5xx = relay trouble, retry later; 403/404 = endpoint/proxy issue, update picoclaw or fix proxy
  2. curl -v the same URL to confirm it is reproducible outside picoclaw
  3. Retry after a short backoff for 502/503/504
  4. Update picoclaw to the latest release so endpoint paths match the relay
Defensive patterns

Strategy: retry

Type guard

func isRetryableStatus(err error) bool {
	msg := err.Error()
	return strings.Contains(msg, "unexpected status 502") ||
		strings.Contains(msg, "unexpected status 503") ||
		strings.Contains(msg, "unexpected status 504") ||
		strings.Contains(msg, "unexpected status 429")
}

Try / catch

err := doWeComJSONGet(ctx, client, target, out)
if isRetryableStatus(err) {
	time.Sleep(backoff)
	err = doWeComJSONGet(ctx, client, target, out)
}
if err != nil {
	return err
}

Prevention

When it happens

Trigger: Relay or its CDN returning 502/503/504; 404 after an endpoint path change between picoclaw and relay versions; 429 from rate limiting; a proxy returning an HTML block page.

Common situations: Relay outage or rolling deploy during login; old picoclaw against a moved endpoint; corporate proxy blocking the relay with a 403 page.

Related errors


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