yikart/AiToEarn · error · UnauthorizedException
Token已过期,请重新登录
Error message
Token已过期,请重新登录
What it means
decodeToken strips the 'Bearer ' prefix and calls jwtService.decode; when decoding fails with TokenExpiredError it throws UnauthorizedException 'Token已过期,请重新登录'. The JWT is well-formed but its exp claim has passed, so it is no longer valid.
Source
Thrown at project/aitoearn-electron/server/src/auth/auth.service.ts:52
* @returns
*/
async resetToken(tokenInfo: TokenInfo): Promise<string> {
const payload: TokenInfo = {
phone: tokenInfo.phone,
id: tokenInfo.id,
name: tokenInfo.name,
isManager: tokenInfo.isManager,
};
return this.jwtService.sign(payload);
}
async decodeToken(token: string): Promise<TokenInfo> {
token = token.replace('Bearer ', '');
try {
return this.jwtService.decode(token);
} catch (error) {
if (error.name === 'TokenExpiredError') {
throw new UnauthorizedException('Token已过期,请重新登录');
} else {
throw new UnauthorizedException('Token校验失败,请重新登录');
}
}
}
}
View on GitHub (pinned to d3aa8bea5b)
Solutions
- Have the client refresh the token or re-login to obtain a new JWT.
- Increase token TTL in JwtModule signOptions if sessions are too short.
- Implement automatic token refresh on 401 in the client.
- Check client clock sync if expiry seems premature.
Example fix
// client before
const res = await fetch(url, { headers: { Authorization: token } });
// after
let res = await fetch(url, { headers: { Authorization: token } });
if (res.status === 401) {
token = await refreshToken();
res = await fetch(url, { headers: { Authorization: token } });
} Defensive patterns
Strategy: try-catch
Validate before calling
function isTokenExpired(token) {
try {
const payload = JSON.parse(atob(token.replace('Bearer ', '').split('.')[1]));
return payload.exp * 1000 < Date.now();
} catch { return true; }
} Try / catch
try {
await api.call(token);
} catch (e) {
if (e?.response?.status === 401 && /Token已过期/.test(e.message)) {
token = await refreshOrRelogin();
await api.call(token);
} else throw e;
} Prevention
- Implement proactive token refresh before exp (e.g., at 80% of TTL).
- Treat 401 with 'Token已过期' as a refresh signal, not a fatal error.
- Keep client clock reasonably synced (NTP).
- Persist refresh tokens securely in the Electron app.
When it happens
Trigger: Any authenticated Electron-server request whose Authorization header carries an expired JWT that reaches decodeToken.
Common situations: Client stayed logged in past token TTL; long-running Electron session without refresh; clock skew between client and server making tokens appear expired.
Related errors
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/5a07f027faaf9aa6.
Report an issue: GitHub.