{"record":{"id":"a146e4da2be97fc5","repo":"AlistGo/alist","slug":"unexpected-status-code-d-a146e4","errorCode":null,"errorMessage":"unexpected status code: %d","messagePattern":"unexpected status code: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/sjtu_netdisk/driver.go","lineNumber":166,"sourceCode":"\n\tresp, err := client.R().\n\t\tSetContext(ctx).\n\t\tSetQueryParams(map[string]string{\n\t\t\t\"access_token\":        d.accessToken,\n\t\t\t\"user_id\":             d.UserId,\n\t\t\t\"content_disposition\": \"attachment\",\n\t\t\t\"purpose\":             \"download\",\n\t\t\t\"space_org_id\":        \"1\",\n\t\t}).\n\t\tExecute(http.MethodGet, linkURL)\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// status code is not 301 and 302\n\tif resp.StatusCode() != http.StatusFound && resp.StatusCode() != http.StatusMovedPermanently {\n\t\treturn nil, fmt.Errorf(\"unexpected status code: %d\", resp.StatusCode())\n\t}\n\n\ts3URL := resp.Header().Get(\"Location\")\n\tif s3URL == \"\" {\n\t\treturn nil, fmt.Errorf(\"no Location header in redirect response\")\n\t}\n\n\t// parse TTL from S3 presigned URL's X-Amz-Expires parameter\n\tttl := 2 * time.Hour\n\tif u, parseErr := url.Parse(s3URL); parseErr == nil {\n\t\tif expiresSec, convErr := strconv.Atoi(u.Query().Get(\"X-Amz-Expires\")); convErr == nil && expiresSec > 0 {\n\t\t\tttl = time.Duration(expiresSec) * time.Second\n\t\t}\n\t}\n\n\treturn &model.Link{\n\t\tURL:        s3URL,\n\t\tExpiration: &ttl,","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/sjtu_netdisk/driver.go#L148-L184","documentation":"Thrown by the SJTU netdisk driver's Link (direct-link) method. It asks the API for a download URL and expects an HTTP 301 or 302 redirect; any other status (200 with a body, 401, 403, 5xx) triggers this error. It almost always means the API call itself misbehaved rather than the file being bad.","triggerScenarios":"Calling the download-link endpoint with an expired access_token (401), a file ID that was deleted (404), insufficient permission on the space, or an API change that now returns 200 with the URL in the body instead of a redirect.","commonSituations":"Token refresh raced or failed before the link request; file was removed in the SJTU web UI while cached in AList; jAccount account lacks permission on the shared org space (space_org_id=1); upstream API contract changed after a service update.","solutions":["Retry the download — refreshToken runs before most operations, so a stale token often self-heals on the next attempt","Verify the file still exists and is accessible via the SJTU netdisk web UI","Re-authenticate the driver (update credentials in the AList storage config) to force a clean token","Check whether the API now returns the S3 URL in the response body instead of a Location redirect, and adapt the driver if so"],"exampleFix":"// before\nif resp.StatusCode() != http.StatusFound && resp.StatusCode() != http.StatusMovedPermanently {\n    return nil, fmt.Errorf(\"unexpected status code: %d\", resp.StatusCode())\n}\n// after: include response body to expose the API's error detail\nif resp.StatusCode() != http.StatusFound && resp.StatusCode() != http.StatusMovedPermanently {\n    return nil, fmt.Errorf(\"unexpected status code: %d, body: %s\", resp.StatusCode(), resp.String())\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := driver.Link(ctx, obj, model.LinkArgs{}); err != nil {\n    if strings.Contains(err.Error(), \"unexpected status code\") {\n        time.Sleep(2 * time.Second) // let token refresh settle\n        return driver.Link(ctx, obj, model.LinkArgs{})\n    }\n    return nil, err\n}","preventionTips":["Ensure the jAccount token is refreshed before link operations","Verify file existence before requesting direct links","Wrap link fetching with one retry for transient 401/5xx"],"tags":["sjtu-netdisk","http","download","redirect"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}