{"record":{"id":"ab2f03eb673948b2","repo":"AlistGo/alist","slug":"res-status-ab2f03","errorCode":null,"errorMessage":"res.Status","messagePattern":"res\\.Status","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/github/driver.go","lineNumber":735,"sourceCode":"\ttoken := strings.TrimSpace(d.Token)\n\tif token != \"\" {\n\t\treq.Header.Set(\"Authorization\", \"Bearer \"+token)\n\t}\n\treq.ContentLength = length\n\n\tres, err := base.HttpClient.Do(req)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer res.Body.Close()\n\tresBody, err := io.ReadAll(res.Body)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif res.StatusCode != 201 {\n\t\tvar errMsg ErrResp\n\t\tif err = utils.Json.Unmarshal(resBody, &errMsg); err != nil {\n\t\t\treturn \"\", errors.New(res.Status)\n\t\t} else {\n\t\t\treturn \"\", fmt.Errorf(\"%s: %s\", res.Status, errMsg.Message)\n\t\t}\n\t}\n\tvar resp PutBlobResp\n\tif err = utils.Json.Unmarshal(resBody, &resp); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn resp.Sha, nil\n}\n\nfunc (d *Github) renewParentTrees(path, prevSha, curSha, until string) (string, error) {\n\tfor path != until {\n\t\tpath = stdpath.Dir(path)\n\t\ttree, sha, err := d.getTreeDirectly(path)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/github/driver.go#L717-L753","documentation":"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').","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the token: it must have write access to the target repo (classic token: 'repo' scope; fine-grained: Contents read/write)","Check owner/repo spelling and that the repo exists and is accessible to the token","Check rate-limit headers (X-RateLimit-Remaining) and retry after Retry-After; reduce upload concurrency","If GitHub returns 5xx, wait and retry later"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-flight token and repo accessibility\nreq, _ := http.NewRequest(\"GET\", fmt.Sprintf(\"https://api.github.com/repos/%s/%s\", owner, repo), nil)\nreq.Header.Set(\"Authorization\", \"Bearer \"+token)\nres, _ := http.DefaultClient.Do(req)\nif res.StatusCode != 200 { return fmt.Errorf(\"preflight failed: %s\", res.Status) }","typeGuard":null,"tryCatchPattern":"sha, err := d.putBlob(ctx, stream, up)\nif err != nil {\n\tif strings.Contains(err.Error(), \"401\") || strings.Contains(err.Error(), \"403\") {\n\t\treturn fmt.Errorf(\"token lacks write access or rate-limited: %w\", err)\n\t}\n\tif strings.HasSuffix(err.Error(), \"Server Error\") || strings.Contains(err.Error(), \"5\") {\n\t\ttime.Sleep(backoff); return d.putBlob(ctx, stream, up) // transient\n\t}\n\treturn err\n}","preventionTips":["Use a classic PAT with 'repo' scope or fine-grained PAT with Contents: read+write on the target repo","Watch X-RateLimit-Remaining on responses and back off near zero","Keep upload concurrency low to avoid secondary rate limits","Alert on 401s so expired tokens are rotated quickly"],"tags":["github","http","authentication","rate-limit","upload"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}