yikart/AiToEarn · error · UnauthorizedException

Token校验失败,请重新登录

Error message

Token校验失败,请重新登录

What it means

The else branch of decodeToken: any decode error that is NOT TokenExpiredError becomes UnauthorizedException 'Token校验失败,请重新登录'. The token could not be validated/decoded at all — malformed structure, bad signature, or invalid format.

Source

Thrown at project/aitoearn-electron/server/src/auth/auth.service.ts:54

  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

  1. Re-login to get a fresh, correctly signed token.
  2. Confirm AUTH_SECRET is identical across server instances/environments.
  3. Inspect the Authorization header format: must be 'Bearer <jwt>'.
  4. Decode the token at jwt.io to check its structure and signature.

Example fix

// before
const token = localStorage.getItem('token');
// after
const token = localStorage.getItem('token');
if (!token || token.split('.').length !== 3) await relogin();
Defensive patterns

Strategy: try-catch

Validate before calling

function isWellFormedJwt(token) {
  const t = token.replace(/^Bearer\s+/, '');
  return typeof t === 'string' && t.split('.').length === 3 && t.length > 20;
}

Type guard

function hasJwtShape(t) {
  return typeof t === 'string' && t.split('.').length === 3;
}

Try / catch

try {
  await api.call(token);
} catch (e) {
  if (e?.response?.status === 401 && /Token校验失败/.test(e.message)) {
    await relogin(); // token 结构/签名无效,必须重新登录
  } else throw e;
}

Prevention

When it happens

Trigger: Requests with a corrupted/truncated JWT, a token signed with a different AUTH_SECRET, garbage in the Authorization header after 'Bearer ', or a JsonWebTokenError during decode.

Common situations: Secret rotation between server deploys invalidating old tokens; client sending a raw token without 'Bearer ' handled correctly; token copied from another environment; AUTH_SECRET differing between instances.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/aa7f2e031eda8fbf. Report an issue: GitHub.