AlistGo/alist · error
init captcha token failed: %s
Error message
init captcha token failed: %s
What it means
ensureCaptchaToken POSTs a signed captcha init payload (username/phone metadata) to /v1/shield/captcha/init and throws when the response is an HTTP error, has an error field, or the CaptchaToken is empty. On success the token is stored and set as the X-Captcha-Token header on the account client. The captcha token gates subsequent verification/SMS endpoints.
Source
Thrown at drivers/guangyapan/driver.go:731
resp, err := d.accountClient.R().
SetContext(ctx).
SetBody(map[string]any{
"client_id": d.ClientID,
"action": "POST:/v1/auth/verification",
"device_id": d.DeviceID,
"meta": map[string]any{
"username": normalizePhoneE164(d.PhoneNumber),
"phone_number": normalizePhoneE164(d.PhoneNumber),
"VERIFICATION_PHONE": normalizePhoneE164(d.PhoneNumber),
},
}).
SetResult(&out).
Post("/v1/shield/captcha/init")
if err != nil {
return err
}
if resp.IsError() || out.Error != "" || strings.TrimSpace(out.CaptchaToken) == "" {
return fmt.Errorf("init captcha token failed: %s", d.accountErr(out.ErrorDesc, out.Error, resp))
}
d.CaptchaToken = strings.TrimSpace(out.CaptchaToken)
d.accountClient.SetHeader("X-Captcha-Token", d.CaptchaToken)
op.MustSaveDriverStorage(d)
return nil
}
func normalizeCaptchaUsername(phone string) string {
p := strings.TrimSpace(phone)
p = strings.ReplaceAll(p, " ", "")
p = strings.TrimPrefix(p, "+")
// Keep only digits.
b := make([]rune, 0, len(p))
for _, ch := range p {
if ch >= '0' && ch <= '9' {
b = append(b, ch)
}
}View on GitHub (pinned to 843d9dc814)
Solutions
- Confirm phone_number is a valid E164-ish number for the account.
- Retry after a minute to let anti-bot/rate limits cool down.
- If the protocol changed (e.g. new required fields in the init payload), update the captchaInitResp/request shape in the driver.
Defensive patterns
Strategy: retry
Validate before calling
// cheap pre-checks before captcha init
if d.PhoneNumber == "" {
return errors.New("phone_number required before captcha init")
} Try / catch
if err := d.ensureCaptchaToken(ctx, true); err != nil {
if strings.Contains(err.Error(), "init captcha token failed") {
// shield/anti-bot: back off and retry once
time.Sleep(5 * time.Second)
err = d.ensureCaptchaToken(ctx, true)
}
if err != nil {
return fmt.Errorf("captcha init rejected (possible anti-bot or outage): %w", err)
}
} Prevention
- Keep a stable device_id in config so the provider trusts the client.
- Avoid rapid-fire logins from rotating IPs.
When it happens
Trigger: First SMS login attempt (no stored CaptchaToken), or a forced refresh after captcha_invalid; the init is rejected because of malformed phone metadata, an unrecognized device_id, anti-bot heuristics, or provider outage.
Common situations: phone_number format that normalizePhoneE164/normalizeCaptchaUsername mangles; signing up from a new device/IP that trips anti-bot; provider-side shield service down or its protocol changed.
Related errors
- request verification failed: %s
- validate token failed: status=%d body=%s
- refresh token failed: %s
- verify code failed: %s
- signin failed: %s
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/c4565f76872b5c73.
Report an issue: GitHub.