AlistGo/alist · error

res.Status()

Error message

res.Status()

What it means

toErr is the generic resty-response-to-error converter for the GitHub driver's non-2xx API replies. It tries to unmarshal the body into ErrResp to append GitHub's 'message' field; when the body is not valid JSON (empty body, HTML error page, plain-text proxy response) it degrades to returning errors.New(res.Status()), i.e. the bare status line such as '403 Forbidden'.

Source

Thrown at drivers/github/util.go:44

	TargetPath string
}

func getMessage(tmpl *template.Template, vars *MessageTemplateVars, defaultOpStr string) (string, error) {
	sb := strings.Builder{}
	if err := tmpl.Execute(&sb, vars); err != nil {
		return fmt.Sprintf("%s %s %s", vars.UserName, defaultOpStr, vars.ObjPath), err
	}
	return sb.String(), nil
}

func calculateBase64Length(inputLength int64) int64 {
	return 4 * ((inputLength + 2) / 3)
}

func toErr(res *resty.Response) error {
	var errMsg ErrResp
	if err := utils.Json.Unmarshal(res.Body(), &errMsg); err != nil {
		return errors.New(res.Status())
	} else {
		return fmt.Errorf("%s: %s", res.Status(), errMsg.Message)
	}
}

// Example input:
// a = /aaa/bbb/ccc
// b = /aaa/b11/ddd/ccc
//
// Output:
// ancestor = /aaa
// aChildName = bbb
// bChildName = b11
// aRest = bbb/ccc
// bRest = b11/ddd/ccc
func getPathCommonAncestor(a, b string) (ancestor, aChildName, bChildName, aRest, bRest string) {
	a = utils.FixAndCleanPath(a)
	b = utils.FixAndCleanPath(b)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Inspect the status: 403 -> check X-RateLimit-* headers and honor Retry-After; 5xx -> retry with backoff later
  2. Confirm the token is valid and has the needed scopes (401/403)
  3. If behind a proxy, ensure it forwards GitHub responses untouched
  4. Retry the operation after the wait window; the failure is usually transient
Defensive patterns

Strategy: retry

Validate before calling

// Check rate limits before heavy operations
res, _ := client.R().SetContext(ctx).Get("https://api.github.com/rate_limit")
if res.StatusCode() == 200 {
	var rl struct{ Rate struct{ Remaining int; Reset int64 } }
	_ = utils.Json.Unmarshal(res.Body(), &rl)
	if rl.Rate.Remaining < 10 { return fmt.Errorf("rate limit nearly exhausted; resets at %d", rl.Rate.Reset) }
}

Try / catch

err := someGithubCall()
if err != nil {
	msg := err.Error()
	switch {
	case strings.Contains(msg, "403"): return fmt.Errorf("rate-limited or forbidden: %w", err)
	case strings.Contains(msg, "5"): time.Sleep(30 * time.Second); return someGithubCall()
	}
	return err
}

Prevention

When it happens

Trigger: Any GitHub REST call made through resty that returns an error status with a non-JSON body: 502/504 HTML from a gateway, empty bodies on 403 secondary-rate-limit, corporate proxy interception, or GitHub outage pages.

Common situations: Primary or secondary rate limits (GitHub sometimes omits the JSON body), GitHub incidents, requests routed through a reverse proxy that rewrites error responses.

Related errors


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