yikart/AiToEarn · error · BadRequestException

userId, accountId和query是必须的

Error message

userId, accountId和query是必须的

What it means

Thrown by the searchTweets endpoint when the query string is missing 'accountId' or 'query' (userId comes from the system token). The guard runs before obtaining the account's access token and executing the Twitter recent-search call.

Source

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

  }

  /**
   * 搜索推文
   */
  @Get('tweets/search')
  @ApiOperation({ summary: '搜索推文' })
  @ApiQuery({ name: 'accountId', required: true, description: 'Twitter账号ID' })
  @ApiQuery({ name: 'query', required: true, description: '搜索关键词' })
  @ApiQuery({ name: 'maxResults', required: false, description: '最大结果数', type: 'number' })
  async searchTweets(
    @GetToken() systemToken: TokenInfo,
    @Query('accountId') accountId: string,
    @Query('query') query: string,
    @Query('maxResults') maxResults?: number,
  ) {
    const userId = systemToken.id;
    if (!userId || !accountId || !query) {
      throw new BadRequestException('userId, accountId和query是必须的');
    }

    const accessToken = await this.twitterAuthService.getUserAccessToken(accountId);
    return this.twitterService.searchTweets(accessToken, userId, accountId, query, maxResults);
  }

  /**
   * 对推文点赞、取消点赞
   */
  @Post('tweets/rate')
  @ApiOperation({ summary: '对推文点赞、取消点赞' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        accountId: { type: 'string', description: '账号ID' },
        tweetId: { type: 'string', description: '推文ID' },
        rating: { type: 'string', description: '点赞 like、取消点赞  unlike' }

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Provide a non-empty query string and accountId as query parameters.
  2. URL-encode the query (e.g. encodeURIComponent) so it survives URL construction.
  3. Block the client-side submit when the search input is empty.
  4. Verify authentication so systemToken.id is non-empty.

Example fix

// before
const url = `/twitter/search?accountId=${accountId}&query=${query}`;
// after
const url = `/twitter/search?accountId=${encodeURIComponent(accountId)}&query=${encodeURIComponent(query)}`;
Defensive patterns

Strategy: validation

Validate before calling

const q = searchInput.trim();
if (!q || !accountId) return; // don't call the API
await api.get('/twitter/search', { params: { query: q, accountId, maxResults } });

Type guard

function canSearch(p: unknown): p is { query: string; accountId: string } {
  const o = p as any;
  return typeof o?.query === 'string' && o.query.trim().length > 0 && typeof o?.accountId === 'string' && o.accountId.length > 0;
}

Try / catch

try {
  const results = await api.get('/twitter/search', { params: { query, accountId } });
} catch (e) {
  if (e.response?.status === 400) setSearchError('请输入搜索内容并选择账号');
}

Prevention

When it happens

Trigger: GET to searchTweets without ?query=... or ?accountId=..., empty-string values, or an invalid system token so userId is falsy. maxResults is optional and does not trigger this error.

Common situations: Search box submitted empty; accountId not yet selected in a multi-account UI; special characters in query dropped during URL construction leaving an empty value.

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/dc161fb42acd4ec3. Report an issue: GitHub.