AlistGo/alist · error

res.Status

Error message

res.Status

What it means

This is the blob-upload failure path in putBlob: the GitHub Contents API was expected to return HTTP 201 (Created) but returned another status, and the response body could not be unmarshalled into the ErrResp struct, so the driver falls back to surfacing the bare HTTP status line (e.g. '401 Unauthorized', '404 Not Found', '403 rate limit exceeded').

Source

Thrown at drivers/github/driver.go:735

	token := strings.TrimSpace(d.Token)
	if token != "" {
		req.Header.Set("Authorization", "Bearer "+token)
	}
	req.ContentLength = length

	res, err := base.HttpClient.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	resBody, err := io.ReadAll(res.Body)
	if err != nil {
		return "", err
	}
	if res.StatusCode != 201 {
		var errMsg ErrResp
		if err = utils.Json.Unmarshal(resBody, &errMsg); err != nil {
			return "", errors.New(res.Status)
		} else {
			return "", fmt.Errorf("%s: %s", res.Status, errMsg.Message)
		}
	}
	var resp PutBlobResp
	if err = utils.Json.Unmarshal(resBody, &resp); err != nil {
		return "", err
	}
	return resp.Sha, nil
}

func (d *Github) renewParentTrees(path, prevSha, curSha, until string) (string, error) {
	for path != until {
		path = stdpath.Dir(path)
		tree, sha, err := d.getTreeDirectly(path)
		if err != nil {
			return "", err
		}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Verify the token: it must have write access to the target repo (classic token: 'repo' scope; fine-grained: Contents read/write)
  2. Check owner/repo spelling and that the repo exists and is accessible to the token
  3. Check rate-limit headers (X-RateLimit-Remaining) and retry after Retry-After; reduce upload concurrency
  4. If GitHub returns 5xx, wait and retry later
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight token and repo accessibility
req, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s/%s", owner, repo), nil)
req.Header.Set("Authorization", "Bearer "+token)
res, _ := http.DefaultClient.Do(req)
if res.StatusCode != 200 { return fmt.Errorf("preflight failed: %s", res.Status) }

Try / catch

sha, err := d.putBlob(ctx, stream, up)
if err != nil {
	if strings.Contains(err.Error(), "401") || strings.Contains(err.Error(), "403") {
		return fmt.Errorf("token lacks write access or rate-limited: %w", err)
	}
	if strings.HasSuffix(err.Error(), "Server Error") || strings.Contains(err.Error(), "5") {
		time.Sleep(backoff); return d.putBlob(ctx, stream, up) // transient
	}
	return err
}

Prevention

When it happens

Trigger: POST to repos/{owner}/{repo}/git/blobs returns non-201: 401 when the token is invalid/expired, 403 for missing repo scope or rate limiting, 404 for wrong repo/owner or private repo without auth, 5xx on GitHub outages — and the body is empty/HTML instead of the expected JSON error envelope.

Common situations: Personal access token lacking 'Contents: read and write' permission (fine-grained PATs), token expired, repo renamed or deleted, secondary rate limits during bulk uploads, GitHub API incident.

Related errors


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