AlistGo/alist · error

request failed: status=%d body=%s

Error message

request failed: status=%d body=%s

What it means

postAPI's first-line failure: a POST to api.guangyapan.com returned 401 or 403, and the storage has no RefreshToken, so automatic token refresh is impossible. The status and raw body are embedded. It indicates an unauthenticated/expired session with no recovery path configured.

Source

Thrown at drivers/guangyapan/driver.go:828

func (d *GuangYaPan) postAPI(ctx context.Context, path string, body any, out any) error {
	if strings.TrimSpace(d.AccessToken) == "" {
		return errors.New("access token is empty")
	}
	if err := d.apiRateLimitWait(ctx, path); err != nil {
		return err
	}
	resp, err := d.apiClient.R().
		SetContext(ctx).
		SetHeader("Authorization", "Bearer "+d.AccessToken).
		SetBody(body).
		SetResult(out).
		Post(path)
	if err != nil {
		return err
	}
	if resp.StatusCode() == 401 || resp.StatusCode() == 403 {
		if strings.TrimSpace(d.RefreshToken) == "" {
			return fmt.Errorf("request failed: status=%d body=%s", resp.StatusCode(), resp.String())
		}
		if err := d.refreshToken(ctx); err != nil {
			return err
		}
		resp, err = d.apiClient.R().
			SetContext(ctx).
			SetHeader("Authorization", "Bearer "+d.AccessToken).
			SetBody(body).
			SetResult(out).
			Post(path)
		if err != nil {
			return err
		}
	}
	if resp.IsError() {
		return fmt.Errorf("request failed: status=%d body=%s", resp.StatusCode(), resp.String())
	}
	return nil

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Complete a full login (SMS login with phone_number + verify_code) so both tokens are stored.
  2. If tokens were exported from elsewhere, re-obtain them with the same ClientID the driver uses.
  3. Confirm the account is not locked/disabled (check the embedded body for the provider's reason).
Defensive patterns

Strategy: try-catch

Validate before calling

// before heavy API use, confirm auth is recoverable
if strings.TrimSpace(d.AccessToken) == "" && strings.TrimSpace(d.RefreshToken) == "" {
    return errors.New("guangyapan storage has no tokens; complete SMS login first")
}

Try / catch

if err := d.postAPI(ctx, path, body, out); err != nil {
    if strings.Contains(err.Error(), "status=401") || strings.Contains(err.Error(), "status=403") {
        if strings.TrimSpace(d.RefreshToken) == "" {
            return errors.New("session expired and no refresh token stored - redo SMS login")
        }
    }
    return err
}

Prevention

When it happens

Trigger: Any postAPI call (list, task status, upload token, offline ops) with expired AccessToken while RefreshToken is empty - e.g. storage configured with only an access token, or SMS login state lost its refresh token.

Common situations: User pasted only an access token into config; refresh token was cleared by a failed refresh; tokens from a different client_id.

Related errors


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