yikart/AiToEarn · warning · BadRequestException
状态数据不完整
Error message
状态数据不完整
What it means
After finding state data in Redis, handleAuthorizationCallback destructures { userId, codeVerifier } from it; if either field is missing it throws BadRequestException('状态数据不完整') ('state data incomplete'). codeVerifier is required for the PKCE token exchange and userId to attribute the connection, so an entry lacking them is unusable.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.auth.service.ts:194
// parsedState = JSON.parse(decodeURIComponent(state));
// } catch (error) {
// this.logger.error('无法解析状态参数:', error);
// throw new BadRequestException('无效的状态参数格式');
// }
// 从Redis获取保存的状态信息
// const originalState = parsedState.state;
const stateDataJson = await this.redisService.get(`tiktok:state:${state}`);
if (!stateDataJson) {
throw new BadRequestException('无效的状态参数或状态已过期');
}
// 解析状态数据
const stateData = JSON.parse(stateDataJson);
console.log('stateData:------', stateData);
const { userId, codeVerifier } = stateData;
if (!userId || !codeVerifier) {
throw new BadRequestException('状态数据不完整');
}
// 删除Redis中的状态信息
await this.redisService.del(`tiktok:state:${state}`);
try {
// 使用授权码交换令牌,并传入codeVerifier
const tokenResponse = await this.exchangeCodeForTokens(code, codeVerifier);
console.log("获取授权码成功!", tokenResponse);
// 获取用户信息
const userProfile = await this.getTikTokUserProfile(tokenResponse.access_token, tokenResponse.open_id);
// 更新或创建TikTok账户信息
await this.updateTikTokAccountInfo(
userId,
userProfile.open_id,
tokenResponse.access_token,
tokenResponse.refresh_token,View on GitHub (pinned to d3aa8bea5b)
Solutions
- Check what getAuthorizationUrl actually stores and confirm field names (userId, codeVerifier) match exactly
- Flush stale tiktok:state:* keys after changing the state payload schema, or version the keys (tiktok:state:v2:<state>)
- Have the user restart authorization to generate fresh, complete state data
- Add a validation/DTO check when writing state so incomplete entries are rejected at write time
Example fix
// before
const { userId, codeVerifier } = stateData;
if (!userId || !codeVerifier) {
throw new BadRequestException('状态数据不完整');
}
// after
const { userId, codeVerifier } = stateData ?? {};
if (typeof userId !== 'string' || typeof codeVerifier !== 'string') {
throw new BadRequestException('Stored TikTok state data is incomplete; restart authorization');
} Defensive patterns
Strategy: type-guard
Validate before calling
const raw = await redis.get(`tiktok:state:${state}`);
const parsed = raw ? JSON.parse(raw) : null;
if (!parsed?.userId || !parsed?.codeVerifier) {
return res.redirect('/connect/tiktok?reason=state_incomplete');
} Type guard
function isCompleteState(d: unknown): d is { userId: string; codeVerifier: string } {
return !!d && typeof d === 'object'
&& typeof (d as any).userId === 'string'
&& typeof (d as any).codeVerifier === 'string';
} Try / catch
try {
return await tiktokAuthService.handleAuthorizationCallback(state, code);
} catch (err) {
if (err instanceof BadRequestException && err.message.includes('不完整')) {
return res.redirect('/connect/tiktok?reason=state_corrupted');
}
throw err;
} Prevention
- Validate the state payload at write time in getAuthorizationUrl
- Version the Redis key schema so old-format entries never match new readers
- Clear stale tiktok:state:* keys after deploying schema changes
- Wrap JSON.parse in try/catch to treat corrupted values as expired state
When it happens
Trigger: Calling handleAuthorizationCallback when the Redis value for the state parses as JSON but lacks userId or codeVerifier — i.e. the state was written with incomplete fields (older version of the writer code, manual Redis edit, corrupted or truncated value, or a JSON shape change between versions).
Common situations: Deploy where getAuthorizationUrl was changed (field renamed, e.g. codeVerifier -> code_verifier) but old-format state entries persist in Redis; someone manually injected test state into Redis; JSON.parse of a non-conforming cached value.
Related errors
- 无效的状态参数或状态已过期
- No response from Gemini
- ResponseCode.ChannelAuthSessionInvalid
- ChannelAuthRefreshTokenMissing
- userId是必需的
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/d10931755f348b6e.
Report an issue: GitHub.