yikart/AiToEarn · error · BadRequestException

token和mail是必须的

Error message

token和mail是必须的

What it means

The GET /plat/twitter/auth/url endpoint starts Twitter OAuth by requiring a valid system JWT (extracted via @GetToken() into systemToken) and a `mail` query parameter. If the request lacks an authenticatable token (systemToken.id falsy) or omits mail, the controller throws BadRequestException('token和mail是必须的') with HTTP 400 before generating the authorization URL.

Source

Thrown at project/aitoearn-electron/server/src/modules/plat/twitter/twitter.controller.ts:30

@Controller('plat/twitter')
export class TwitterController {
  constructor(
    private readonly twitterAuthService: TwitterAuthService,
    private readonly twitterService: TwitterService,
  ) {}

  /**
   * 获取Twitter授权URL
   */
  @Get('auth/url')
  @ApiOperation({ summary: '获取Twitter授权URL' })
  @ApiQuery({ name: 'mail', required: false, description: '用户邮箱' })
  async getAuthUrl(
    @GetToken() systemToken: TokenInfo,
    @Query('mail') mail: string,
  ) {
    if (!systemToken.id || !mail) {
      throw new BadRequestException('token和mail是必须的');
    }
    return this.twitterAuthService.getAuthorizationUrl(systemToken.id, mail);
  }

  /**
   * 处理Twitter OAuth回调
   */
  @Get('auth/callback')
  @ApiOperation({ summary: 'Twitter授权回调' })
  // @ApiQuery({ name: 'code', required: true, description: '授权码' })
  // @ApiQuery({ name: 'state', required: true, description: '状态值' })
  @Public()
  async handleOAuthCallback(
    // @GetToken() systemToken: TokenInfo,
    @Query('code') code: string,
    @Query('state') state: string,
    @Res() res: Response,
  ) {

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Attach a valid system JWT (Authorization header) obtained from login before calling this endpoint
  2. Append the user's email as a query param: GET /plat/twitter/auth/url?mail=user@example.com
  3. Check why systemToken.id is empty — expired token or missing auth guard configuration; re-login to refresh the JWT
  4. Trim/validate the mail input client-side before the request

Example fix

// before
await api.get('/plat/twitter/auth/url');
// after
await api.get('/plat/twitter/auth/url', {
  params: { mail: user.email },
  headers: { Authorization: `Bearer ${systemToken}` },
});
Defensive patterns

Strategy: validation

Validate before calling

if (!systemToken || !userEmail) {
  throw new Error('Cannot start Twitter OAuth: missing auth token or mail');
}
await api.get('/plat/twitter/auth/url', { params: { mail: userEmail }, headers: { Authorization: `Bearer ${systemToken}` } });

Type guard

function canStartOAuth(t: unknown, mail: unknown): t is { id: string } {
  return !!t && typeof (t as any).id === 'string' && (t as any).id.length > 0
    && typeof mail === 'string' && mail.includes('@');
}

Try / catch

try {
  return await api.get('/plat/twitter/auth/url', { params: { mail } });
} catch (e) {
  if (e.response?.status === 400) {
    // token missing/expired or mail absent — re-login and collect mail, then retry
    await relogin();
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling GET /plat/twitter/auth/url without an Authorization header / invalid expired JWT; calling with a valid token but no ?mail= query; passing mail as an empty string.

Common situations: Frontend forgetting to attach the auth token in an early onboarding step; Swagger 'try it out' without authorizing; mail collected later in the signup flow than the OAuth kickoff; URL-encoded mail lost by a redirect.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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