yikart/AiToEarn · error · BadRequestException
无效的账号或刷新令牌丢失
Error message
无效的账号或刷新令牌丢失
What it means
A BadRequestException thrown by getUserAccessToken when no account token record exists in MongoDB for the given accountId+TIKTOK platform, or the record exists but its refreshToken field is empty. This is a local pre-condition check before attempting any refresh call.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.auth.service.ts:507
*/
async getUserAccessToken(accountId: string): Promise<string> {
this.logger.log(`获取TikTok访问令牌: accountId=${accountId}`);
// 先检查Redis缓存
const cachedToken = await this.redisService.get(`tiktok:accessToken:${accountId}`);
if (cachedToken && cachedToken.access_token) {
this.logger.log("从Redis获取到有效令牌");
return cachedToken.access_token;
}
// 如果缓存中没有,尝试刷新
const accountTokenInfo = await this.accountTokenModel.findOne({
accountId: accountId,
platform: TokenPlatform.TIKTOK
});
if (!accountTokenInfo || !accountTokenInfo.refreshToken) {
throw new BadRequestException('无效的账号或刷新令牌丢失');
}
// 刷新并获取新令牌
const refreshResult = await this.refreshAccessToken(
accountTokenInfo.userId,
accountTokenInfo.accountId,
accountTokenInfo.refreshToken
);
// 刷新后再次从Redis获取
const newToken = await this.redisService.get(`tiktok:accessToken:${accountId}`);
if (!newToken || !newToken.access_token) {
throw new BadRequestException('刷新令牌后未能获取访问令牌');
}
return newToken.access_token;
}
View on GitHub (pinned to d3aa8bea5b)
Solutions
- Verify the accountId exists in the accountToken collection with platform='TIKTOK' and a non-empty refreshToken.
- If refreshToken is missing, ask the user to complete the TikTok OAuth flow again via /tiktok/auth-url.
- Confirm the caller passes the correct accountId (not userId) and that you're querying the right environment's database.
- Check whether token cleanup/invalidation logic recently removed the refreshToken field.
Example fix
// before
if (!accountTokenInfo || !accountTokenInfo.refreshToken) {
throw new BadRequestException('无效的账号或刷新令牌丢失');
}
// after
if (!accountTokenInfo) {
throw new BadRequestException(`账号 ${accountId} 未绑定 TikTok,请先完成授权`);
}
if (!accountTokenInfo.refreshToken) {
throw new BadRequestException(`账号 ${accountId} 刷新令牌已失效,请重新授权`);
} Defensive patterns
Strategy: validation
Validate before calling
// before calling access-token endpoint
const rec = await db.accountTokens.findOne({ accountId, platform: 'TIKTOK' });
if (!rec?.refreshToken) {
throw new Error(`account ${accountId} has no TikTok refresh token; run OAuth flow first`);
} Type guard
function hasUsableTikTokAccount(t: unknown): t is { accountId: string; refreshToken: string } {
return typeof t === 'object' && t !== null &&
typeof (t as any).refreshToken === 'string' && (t as any).refreshToken.length > 0;
} Try / catch
try {
const token = await api.getTikTokAccessToken(accountId);
} catch (e) {
if (/刷新令牌丢失/.test((e as Error).message)) {
const authUrl = await api.getTikTokAuthUrl(userId, mail);
return redirectUserToReauth(authUrl);
}
throw e;
} Prevention
- Verify account binding (accountId + platform) before calling token endpoints.
- Pass accountId, not userId, to the lookup.
- Keep environment databases separate and query the right one.
- Surface a re-auth CTA to users when the refresh token is missing.
When it happens
Trigger: Calling GET /tiktok/access-token (getUserAccessToken) with an accountId that was never authorized, the account was deleted, or the stored document has refreshToken unset/null — e.g. it was cleared after a previous invalid_refresh_token failure.
Common situations: Caller passes a userId instead of accountId, account authorized on a different environment (cn vs ai) with a separate database, refresh token scrubbed by cleanup logic, account revoked in TikTok and the app cleared tokens.
Related errors
- ChannelAuthRefreshTokenMissing
- No response from Gemini
- No subtitle entries in response
- ResponseCode.AccountCreateFailed
- ChannelAuthRefreshTokenMissing
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/bfed6a81e0a2c157.
Report an issue: GitHub.