fish2018/pansou · error

创建 Anubis 验证请求失败

Error message

创建 Anubis 验证请求失败: %w

What it means

This error is returned by MiosouPlugin.completeAnubisChallenge when http.NewRequestWithContext fails to construct the GET request to baseURL+"/" — the first step of solving the Anubis challenge. Since baseURL is a compile-time constant, this indicates the URL string is malformed (unparseable) or the supplied context is invalid; it is wrapped by ensureGate's 人机验证未通过 error.

Solutions

  1. Log baseURL and run url.Parse on it to confirm it is valid with an https scheme
  2. Check any config/constant override of baseURL for stray whitespace or typos
  3. Ensure the context passed in is fresh and not canceled before the challenge begins
  4. This is deterministic — fix the value; do not rely on the 3-attempt retry loop

Example fix

// before
baseURL = "miosou.example .com" // invalid: contains space
// after
baseURL = "https://miosou.example.com"
if _, err := url.Parse(baseURL); err != nil {
    panic("invalid baseURL: " + err.Error())
}
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate baseURL before constructing challenge requests
u, err := url.Parse(baseURL + "/")
if err != nil || (u.Scheme != "http" && u.Scheme != "https") || u.Host == "" {
    return fmt.Errorf("invalid baseURL %q: %v", baseURL, err)
}

Type guard

func validBaseURL(raw string) bool {
    u, err := url.Parse(raw)
    return err == nil && u.Host != "" && (u.Scheme == "http" || u.Scheme == "https")
}

Try / catch

req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL+"/", nil)
if err != nil {
    return fmt.Errorf("bad challenge URL %q: %w", baseURL+"/", err)
}

Prevention

When it happens

Trigger: completeAnubisChallenge calls http.NewRequestWithContext(ctx, http.MethodGet, baseURL+"/", nil) and it returns err because the URL cannot be parsed (bad scheme/characters in baseURL) or ctx is already canceled/invalid.

Common situations: baseURL misconfigured with whitespace/control characters or missing scheme; a refactor passes an already-canceled context into ensureGate→completeAnubisChallenge; accidental string concatenation breaking the URL.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/221d4c60670f9f7b. Report an issue: GitHub.

Appendix: source

Thrown at plugin/miosou/miosou.go:157

	var lastErr error
	for attempt := 0; attempt < 3; attempt++ {
		ctx, cancel := context.WithTimeout(context.Background(), gateTimeout)
		err := p.completeAnubisChallenge(ctx)
		cancel()
		if err == nil {
			p.gateReady = true
			return nil
		}
		lastErr = err
	}
	return fmt.Errorf("[%s] 人机验证未通过: %w", p.Name(), lastErr)
}

func (p *MiosouPlugin) completeAnubisChallenge(ctx context.Context) error {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL+"/", nil)
	if err != nil {
		return fmt.Errorf("创建 Anubis 验证请求失败: %w", err)
	}
	setPageHeaders(req)
	resp, err := p.client.Do(req)
	if err != nil {
		return fmt.Errorf("获取 Anubis 验证题目失败: %w", err)
	}
	body, readErr := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
	resp.Body.Close()
	if readErr != nil {
		return fmt.Errorf("读取 Anubis 验证题目失败: %w", readErr)
	}
	challenge, found, err := parseAnubisChallenge(body)
	if err != nil {
		return err
	}
	if !found {
		if resp.StatusCode == http.StatusOK && !isAnubisGateResponse(resp) {
			return nil

View on GitHub (pinned to beaa561337)