{"record":{"id":"c4ee37b9e44f3024","repo":"hmjz100/LinkSwift","slug":"url-c4ee37","errorCode":null,"errorMessage":"[迅雷云盘] 获取文件 URL 失败","messagePattern":"\\[迅雷云盘\\] 获取文件 URL 失败","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"（改）网盘直链下载助手.user.js","lineNumber":7783,"sourceCode":"\t\t\t\tconst batchSize = 15;\r\n\t\t\t\tlet proc = 0;\r\n\t\t\t\t$doc.find(\".loading-popup .loading-title\").html(`链接获取中`);\r\n\t\t\t\t$doc.find(\".loading-popup .swal2-html-container\").html(`<div>正在获取文件对应的下载链接~</div>`);\r\n\t\t\t\tfor (let i = 0; i < selects.length; i += batchSize) {\r\n\t\t\t\t\tconst batch = selects.slice(i, i + batchSize);\r\n\t\t\t\t\tconst queue = [];\r\n\t\t\t\t\tbatch.forEach((item, localIndex) => {\r\n\t\t\t\t\t\tconst globalIndex = i + localIndex;\r\n\t\t\t\t\t\tqueue.push(this.getFileUrl(item, globalIndex)\r\n\t\t\t\t\t\t\t.then(val => {\r\n\t\t\t\t\t\t\t\tproc++;\r\n\t\t\t\t\t\t\t\t$doc.find(\".loading-popup .swal2-html-container\").html(`<div>已获取 ${proc} / ${selects.length} 个链接~</div>`);\r\n\t\t\t\t\t\t\t\treturn val;\r\n\t\t\t\t\t\t\t}));\r\n\t\t\t\t\t});\r\n\t\t\t\t\tconst res = await Promise.all(queue).catch(e => {\r\n\t\t\t\t\t\tif (e instanceof Error) throw e;\r\n\t\t\t\t\t\tthrow new Error(e?.message || e || \"[迅雷云盘] 获取文件 URL 失败\");\r\n\t\t\t\t\t});\r\n\t\t\t\t\tres.forEach(val => {\r\n\t\t\t\t\t\tselects[val.index].downloadUrl = val.downloadUrl;\r\n\t\t\t\t\t});\r\n\t\t\t\t\tawait base.sleep(1000);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthrow new Error(\"提示：<br/>页面错误~\");\r\n\t\t\t}\r\n\t\t\ttemp.links = [selects, {\r\n\t\t\t\tisFolder: v => v.kind === \"drive#folder\",\r\n\t\t\t\tgetFileName: v => v.name,\r\n\t\t\t\tgetFileSize: v => v.size,\r\n\t\t\t\tgetFileLink: v => v.downloadUrl,\r\n\t\t\t\tgetFileMirror: v => base.getMirrorList(v, config.$xunlei.api.mirror),\r\n\t\t\t\ttooltip: config.$xunlei.dom\r\n\t\t\t}];\r\n\t\t\tbase.showMainDialog(config.base.dom.button[temp.mode].title, base.generateDOM(temp.links), config.base.dom.button[temp.mode].footer);\r","sourceCodeStart":7765,"sourceCodeEnd":7801,"githubUrl":"https://github.com/hmjz100/LinkSwift/blob/417ea5e28a3e1a90339710e17356e9fd22b8a34b/（改）网盘直链下载助手.user.js#L7765-L7801","documentation":"Wrapper error in the 迅雷云盘 getLink batch flow, mirroring the Tianyi case: when Promise.all over per-file getFileUrl promises rejects with a non-Error value, it is re-thrown as '[迅雷云盘] 获取文件 URL 失败'. It masks the underlying per-file rejection (e.g. captcha failure, link API error object).","triggerScenarios":"Batch getLink with batchSize 15: any getFileUrl call rejects with a non-Error — commonly the link API returning a JSON error object (X-Captcha-Token rejected, rate limit) instead of throwing an Error.","commonSituations":"Captcha token expired mid-batch causing per-file rejections; Xunlei link endpoint rate limiting rapid batch requests; server error bodies returned as resolved values then rejected downstream as non-Errors.","solutions":["Retry after a pause (the flow already sleeps 1000ms between batches — increase batch interval if rate-limited)","Refresh the page / re-login to obtain a fresh captcha token before retrying","Log the original rejection before the wrapper replaces it and fix that root cause","Update the userscript if the Xunlei link API response format changed"],"exampleFix":"// before\nthrow new Error(e?.message || e || \"[迅雷云盘] 获取文件 URL 失败\");\n// after (preserve root cause)\nthrow e instanceof Error ? e : new Error(\"[迅雷云盘] 获取文件 URL 失败: \" + JSON.stringify(e));","handlingStrategy":"retry","validationCode":"if (!hasValidToken(getCachedXunleiToken())) { await refreshToken(); }\nif (selects.length === 0 || selects.every(i => i.kind !== 'drive#file')) return;","typeGuard":"function isError(e) { return e instanceof Error; }","tryCatchPattern":"try { await getLink(); } catch (e) { if (e.message.includes('迅雷云盘.*获取文件 URL')) { await sleep(3000); return getLink(); } throw e; }","preventionTips":["Throttle batch requests to avoid rate limiting","Refresh captcha tokens between batches","Reduce batchSize from 15 on repeated failures","Preserve original rejection details"],"tags":["network","xunlei","rate-limit","error-wrapping"],"backgroundTag":"non-error-rejection","analyzedSha":"417ea5e28a3e1a90339710e17356e9fd22b8a34b","analyzedAt":"2026-09-02T18:13:32.837Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}