{"record":{"id":"9be5076e098b0ea9","repo":"AlistGo/alist","slug":"not-get-file-info","errorCode":null,"errorMessage":"not get file info","messagePattern":"not get file info","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/115/util.go","lineNumber":156,"sourceCode":"\tfile.From(&fileInfo.FileInfo)\n\treturn FileObj{\n\t\tFile:     *file,\n\t\tThumbURL: fileInfo.ThumbURL,\n\t}\n}\n\nfunc (d *Pan115) getFileInfoWithThumb(queryKey, queryVal string) (*fileInfoWithThumb, error) {\n\tresult := getFileInfoResponseWithThumb{}\n\treq := d.client.NewRequest().\n\t\tSetQueryParam(queryKey, queryVal).\n\t\tForceContentType(\"application/json;charset=UTF-8\").\n\t\tSetResult(&result)\n\tresp, err := req.Get(driver115.ApiFileInfo)\n\tif err := driver115.CheckErr(err, &result, resp); err != nil {\n\t\treturn nil, err\n\t}\n\tif len(result.Files) == 0 {\n\t\treturn nil, errors.New(\"not get file info\")\n\t}\n\treturn result.Files[0], nil\n}\n\nfunc (d *Pan115) getFilesPageWithThumb(dirID, apiURL string, limit, offset int64) (*fileListRespWithThumb, error) {\n\tif dirID == \"\" {\n\t\tdirID = \"0\"\n\t}\n\tresult := fileListRespWithThumb{}\n\tparams := map[string]string{\n\t\t\"aid\":              \"1\",\n\t\t\"cid\":              dirID,\n\t\t\"o\":                driver115.FileOrderByTime,\n\t\t\"asc\":              \"1\",\n\t\t\"offset\":           strconv.FormatInt(offset, 10),\n\t\t\"show_dir\":         \"1\",\n\t\t\"limit\":            strconv.FormatInt(limit, 10),\n\t\t\"snap\":             \"0\",","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/115/util.go#L138-L174","documentation":"Error path in alist's ServeHTTP for a single-range request ('Range: bytes=start-end'). The parsed range ra is passed to RangeReadCloser.RangeRead; if the storage driver fails to open a reader for that byte window, the driver's error message is sent to the client with HTTP 416, upgraded to 429 when the error is ErrExceedMaxConcurrency (serve.go:146). As with the no-range path, 416 is misleading — the range was already validated by http_range.ParseRange, so this actually means 'backend reader failed'.","triggerScenarios":"A GET with exactly one valid Range entry where the backend cannot serve that slice: driver's ranged GET to the remote returns an error (expired URL, auth, network), a local driver cannot seek to the offset, or the shared ConcurrencyLimit is at zero so download() returns ErrExceedMaxConcurrency and the client gets 429 with body 'ExceedMaxConcurrency'.","commonSituations":"Video players and download managers (VLC, IDM, browsers resuming downloads) that issue byte-range requests against alist proxies; seek-to-position playback after the remote direct link has expired; remote storages that don't support ranged reads; concurrency exhaustion when multiple streams seek simultaneously; expired OAuth tokens on cloud drivers.","solutions":["Inspect the response body text — it is the verbatim backend error and identifies the failing operation (auth, 404, timeout, ExceedMaxConcurrency).","For 'ExceedMaxConcurrency'/429: lower the number of concurrent streams (player setting 'single stream', fewer parallel segments) or raise the driver/downloader concurrency limit in alist.","If the error indicates the remote rejected the range (e.g., 416/403 from upstream), verify the remote storage actually supports Range requests and that the file size hasn't changed.","Refresh or reconfigure the storage driver (re-login token) if errors mention authorization.","Retry the request after clearing cached links so alist re-fetches a fresh direct URL."],"exampleFix":"// before: video player opens many parallel range connections\nreq, _ := http.NewRequest(\"GET\", url, nil)\nreq.Header.Set(\"Range\", \"bytes=0-\")\nresp, _ := http.DefaultClient.Do(req) // 429 ExceedMaxConcurrency under load\n\n// after: single-stream range request with retry honoring Retry-After/backoff\nfor attempt := 0; attempt < 3; attempt++ {\n    resp, err := http.DefaultClient.Do(req)\n    if err == nil && resp.StatusCode != http.StatusTooManyRequests {\n        break\n    }\n    time.Sleep(time.Duration(1<<attempt) * time.Second)\n}","handlingStrategy":"retry","validationCode":"// Validate the range is in-bounds before requesting, avoiding obvious 416s:\nfunc validRange(start, end int64, size int64) bool {\n    return size > 0 && start >= 0 && start < size && (end < 0 || end >= start) && end < size\n}\n// note: out-of-bounds ranges are filtered by ParseRange/sumRangesSize; a 416 here\n// still means the BACKEND reader failed, so also probe availability with a 1-byte\n// range request before starting long streaming sessions.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Log the response body on any 416/429 from a range request — it is the raw storage-driver error.","Configure players/download managers to use a single stream or low parallelism to avoid ErrExceedMaxConcurrency.","Re-request a fresh link (restart playback / re-resolve the URL) after long idle periods instead of reusing old ones.","Monitor alist logs for the matching driver error to fix root cause (auth, expired link, remote 5xx)."],"tags":["go","http","range-request","alist","streaming","concurrency"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}