hmjz100/LinkSwift · error · Error
错误:<br/>令牌刷新失败,${res?.error_description || res?.error || "未知
Error message
错误:<br/>令牌刷新失败,${res?.error_description || res?.error || "未知错误"} What it means
Thrown during credential/captcha token refresh when the refresh API responds successfully at the HTTP layer but does NOT return a captcha_token. The code expects res.captcha_token plus expires_in to cache a captcha token; if the response lacks it, it surfaces the server's error_description / error fields, falling back to '未知错误'. It indicates the cloud provider refused the token refresh.
Source
Thrown at (改)网盘直链下载助手.user.js:7716
const res = await base.post(config.$xunlei.api.getCaptchaToken, {
client_id: clientId,
action: "get:/drive/v1/about",
device_id: deviceId,
meta: {
username: "", phone_number: "", email: "",
package_name: location.host,
client_version: clientVersion,
captcha_sign: this._getCaptchaSign(clientId, clientVersion, location.host, deviceId, timestamp.toString()),
timestamp: timestamp.toString(),
user_id: userId
}
}, { "Content-Type": "application/json" });
if (res?.captcha_token) {
cap = { token: res.captcha_token, expires_at: new Date(timestamp + res.expires_in * 1000).toString() };
base.setStorage(capKey, cap);
} else {
throw new Error(`错误:<br/>令牌刷新失败,${res?.error_description || res?.error || "未知错误"}`);
}
} else if (!creds || !cap || !clientId || !deviceId) {
throw new Error(`错误:<br/>请先登录网盘后再获取文件呢~`);
}
return { credentials: creds, captcha: cap, device_id: deviceId };
});
},
async getFileUrl(item, index, isRetry = false) {
if (item.downloadUrl) return { index, downloadUrl: item.downloadUrl };
// 获取当前内存中的 token
const token = await this.getToken(false, false).catch(e => {
if (e instanceof Error) throw e;
throw new Error(e?.message || e || "[迅雷云盘] 获取令牌失败");
});
const res = await base.get(config.$xunlei.api.getLink + item.id, {
View on GitHub (pinned to 417ea5e28a)
Solutions
- Log out and log back into the cloud drive in the userscript to regenerate credentials
- Read the embedded error_description in the message (e.g. invalid_grant) and act on it — most often re-authentication
- Clear the userscript's cached storage keys (credentials, captcha) and retry the refresh
- Check system clock accuracy if the error mentions expired/invalid token timestamps
Defensive patterns
Strategy: retry
Validate before calling
const creds = base.getStorage(credsKey);
if (!creds?.refresh_token) { promptLogin(); } Type guard
function hasCaptcha(res) { return typeof res?.captcha_token === 'string' && res.captcha_token.length > 0; } Try / catch
try { await refreshCreds(); } catch (e) { if (e.message.includes('令牌刷新失败')) { clearStoredCredentials(); promptLogin(); } else throw e; } Prevention
- Re-authenticate when password changes elsewhere
- Keep system clock accurate
- Clear cached captcha on repeated refresh failures
- Surface error_description to the user
When it happens
Trigger: Calling the token-refresh endpoint (POST with JSON body) and receiving a JSON body without captcha_token — e.g. {error: 'invalid_grant'} or {error_description: '...'} — typically when stored credentials (creds) are expired, revoked, or the device/client ID is rejected.
Common situations: User logged out or changed password on the cloud drive, invalidating stored refresh credentials; captcha/anti-bot policy change server-side; clock skew making cached captcha look valid; clientId/deviceId mismatch after clearing browser storage.
Related errors
AI-assisted analysis of hmjz100/LinkSwift@417ea5e28a (2026-09-02).
Data as JSON: /api/errors/e2d21398ced17730.
Report an issue: GitHub.