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

  1. Retry after a pause (the flow already sleeps 1000ms between batches — increase batch interval if rate-limited)
  2. Refresh the page / re-login to obtain a fresh captcha token before retrying
  3. Log the original rejection before the wrapper replaces it and fix that root cause
  4. 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

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.