yikart/AiToEarn · error · BadRequestException
获取用户信息失败: ${error.response?.data?.error?.message || error.me
Error message
获取用户信息失败: ${error.response?.data?.error?.message || error.message || error.code} What it means
A BadRequestException thrown by getTikTokUserProfile when the GET to TikTok's /v2/user/info/ endpoint fails or returns an error envelope. It extracts the nested error.message from TikTok's { error: { code, message } } response shape, falling back to axios error.message or error.code.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.auth.service.ts:326
params: {
fields: 'open_id,union_id,avatar_url,bio_description,profile_deep_link,is_verified,follower_count,following_count,likes_count,video_count,username, display_name',
// open_id: openId
},
headers: {
'Authorization': `Bearer ${accessToken}`
}
})
);
console.log(data)
// if (data.error) {
// throw new BadRequestException(`获取用户信息失败: ${data.error.message}`);
// }
return data.data.user;
} catch (error) {
this.logger.error('获取TikTok用户信息失败:', error);
throw new BadRequestException(`获取用户信息失败: ${error.response?.data?.error?.message || error.message || error.code}`);
}
}
/**
* 更新TikTok账户信息
* @param userId 用户ID
* @param tikTokId TikTok用户ID
* @param accessToken 访问令牌
* @param refreshToken 刷新令牌
* @param expires_in 令牌有效期(秒)
*/
async updateTikTokAccountInfo(
userId: string,
tikTokId: string,
accessToken: string,
refreshToken: string,
expires_in: number
): Promise<void> {View on GitHub (pinned to d3aa8bea5b)
Solutions
- Read the nested error message — TikTok names the failing scope or auth problem explicitly.
- Ensure the authorize URL requests user.info.basic (and user.info.profile as needed) in its scope parameter.
- Verify the access_token used is the current one from the latest token exchange, not a stale Redis entry.
- If the token expired, run refreshAccessToken to mint a new one before calling the profile endpoint.
Example fix
// before
const data = await firstValueFrom(this.httpService.get(url, { headers: { Authorization: `Bearer ${accessToken}` } }));
return data.data.user;
// after
if (data.data?.error?.code) {
throw new BadRequestException(`获取用户信息失败: ${data.data.error.code} - ${data.data.error.message}`);
}
return data.data.user; Defensive patterns
Strategy: type-guard
Validate before calling
// before calling user info, confirm token shape and scope
if (!accessToken || accessToken.length < 20) throw new Error('valid access_token required');
// ensure the authorize URL included scope=user.info.basic Type guard
function isTikTokUserPayload(data: unknown): data is { data: { user: { open_id: string; display_name?: string } } } {
return typeof data === 'object' && data !== null &&
typeof (data as any).data?.user?.open_id === 'string';
} Try / catch
try {
const profile = await api.getTikTokUserProfile(token);
} catch (e) {
const msg = (e as any).response?.data?.error?.message ?? (e as Error).message;
if (/access_token|invalid/i.test(msg)) {
token = await api.refreshTikTokToken(accountId);
return retryProfile(token);
}
throw e;
} Prevention
- Always request user.info.basic scope in the authorize URL.
- Refresh expired access tokens before calling user info.
- Validate the token exists in Redis before each profile call.
- Check TikTok's { error: { code, message } } envelope even on HTTP 200.
When it happens
Trigger: Calling user info with an access_token that is expired, revoked, or lacks the user.info.basic scope; the token was refreshed/rotated between exchange and profile fetch; TikTok returns 4xx with an error envelope.
Common situations: Missing user.info.basic scope in the authorize URL's scope parameter, access token expired (TikTok access tokens last ~24h), token stored in Redis was overwritten or evicted, wrong API version path.
Related errors
- 刷新令牌后未能获取访问令牌
- No response from Gemini
- No subtitle entries in response
- ResponseCode.ChannelAccessTokenFailed
- ChannelAuthRefreshTokenMissing
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/31755ddd6d7a987a.
Report an issue: GitHub.