hmjz100/LinkSwift · error · Error
[迅雷云盘] 获取文件 URL 失败
Error message
[迅雷云盘] 获取文件 URL 失败
What it means
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).
Source
Thrown at (改)网盘直链下载助手.user.js:7783
const batchSize = 15;
let proc = 0;
$doc.find(".loading-popup .loading-title").html(`链接获取中`);
$doc.find(".loading-popup .swal2-html-container").html(`<div>正在获取文件对应的下载链接~</div>`);
for (let i = 0; i < selects.length; i += batchSize) {
const batch = selects.slice(i, i + batchSize);
const queue = [];
batch.forEach((item, localIndex) => {
const globalIndex = i + localIndex;
queue.push(this.getFileUrl(item, globalIndex)
.then(val => {
proc++;
$doc.find(".loading-popup .swal2-html-container").html(`<div>已获取 ${proc} / ${selects.length} 个链接~</div>`);
return val;
}));
});
const res = await Promise.all(queue).catch(e => {
if (e instanceof Error) throw e;
throw new Error(e?.message || e || "[迅雷云盘] 获取文件 URL 失败");
});
res.forEach(val => {
selects[val.index].downloadUrl = val.downloadUrl;
});
await base.sleep(1000);
}
} else {
throw new Error("提示:<br/>页面错误~");
}
temp.links = [selects, {
isFolder: v => v.kind === "drive#folder",
getFileName: v => v.name,
getFileSize: v => v.size,
getFileLink: v => v.downloadUrl,
getFileMirror: v => base.getMirrorList(v, config.$xunlei.api.mirror),
tooltip: config.$xunlei.dom
}];
base.showMainDialog(config.base.dom.button[temp.mode].title, base.generateDOM(temp.links), config.base.dom.button[temp.mode].footer);
View on GitHub (pinned to 417ea5e28a)
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
Example fix
// before
throw new Error(e?.message || e || "[迅雷云盘] 获取文件 URL 失败");
// after (preserve root cause)
throw e instanceof Error ? e : new Error("[迅雷云盘] 获取文件 URL 失败: " + JSON.stringify(e)); Defensive patterns
Strategy: retry
Validate before calling
if (!hasValidToken(getCachedXunleiToken())) { await refreshToken(); }
if (selects.length === 0 || selects.every(i => i.kind !== 'drive#file')) return; Type guard
function isError(e) { return e instanceof Error; } Try / catch
try { await getLink(); } catch (e) { if (e.message.includes('迅雷云盘.*获取文件 URL')) { await sleep(3000); return getLink(); } throw e; } Prevention
- Throttle batch requests to avoid rate limiting
- Refresh captcha tokens between batches
- Reduce batchSize from 15 on repeated failures
- Preserve original rejection details
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of hmjz100/LinkSwift@417ea5e28a (2026-09-02).
Data as JSON: /api/errors/c4ee37b9e44f3024.
Report an issue: GitHub.