AlistGo/alist · error

validate token failed: status=%d body=%s

Error message

validate token failed: status=%d body=%s

What it means

validateToken calls GET /v1/user/me on account.guangyapan.com with the current Bearer access token and throws this when the HTTP response is 4xx/5xx (resp.IsError()). It means the token was rejected or the account service errored, before the empty-sub check runs.

Source

Thrown at drivers/guangyapan/driver.go:554

			return errors.New("not logged in yet: please fill verify_code and save storage to finish SMS login")
		}
		return errors.New("access token is empty")
	}
	return d.refreshToken(ctx)
}

func (d *GuangYaPan) validateToken(ctx context.Context) error {
	var me userMeResp
	resp, err := d.accountClient.R().
		SetContext(ctx).
		SetHeader("Authorization", "Bearer "+d.AccessToken).
		SetResult(&me).
		Get("/v1/user/me")
	if err != nil {
		return err
	}
	if resp.IsError() {
		return fmt.Errorf("validate token failed: status=%d body=%s", resp.StatusCode(), resp.String())
	}
	if strings.TrimSpace(me.Sub) == "" {
		return errors.New("validate token failed: empty user sub")
	}
	return nil
}

func (d *GuangYaPan) refreshToken(ctx context.Context) error {
	if strings.TrimSpace(d.RefreshToken) == "" {
		return errors.New("refresh_token is empty")
	}

	var out tokenResp
	resp, err := d.accountClient.R().
		SetContext(ctx).
		SetBody(map[string]any{
			"client_id":     d.ClientID,
			"grant_type":    "refresh_token",

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Read the embedded status: 401/403 means re-authenticate (refresh token or full SMS login); 5xx means retry later.
  2. Trigger refreshToken (or re-run SMS login with phone + verify_code) to obtain fresh tokens.
  3. If body shows invalid_client, confirm ClientID matches the expected default (aMe-8VSlkrbQXpUR) or the provider's current client id.
Defensive patterns

Strategy: retry

Try / catch

if err := d.validateToken(ctx); err != nil {
    if re := d.RefreshToken; strings.TrimSpace(re) != "" {
        if rerr := d.refreshToken(ctx); rerr == nil {
            err = d.validateToken(ctx) // retry once with fresh token
        }
    }
    if err != nil {
        return fmt.Errorf("guangyapan auth needs full re-login: %w", err)
    }
}

Prevention

When it happens

Trigger: Any flow that calls validateToken (storage init/refresh path) with an expired, revoked, or malformed AccessToken, or when the account API returns 5xx; status and raw body are embedded in the message.

Common situations: Access token expired and refresh token is also stale; the token was copied with extra whitespace or truncated; GuangYaPan account service outage or changed auth scheme.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/eef6ff52c9a3375d. Report an issue: GitHub.