yikart/AiToEarn · warning · BadRequestException

只能选择一个参数: allThreadsRelatedToChannelId, id, videoId

Error message

只能选择一个参数: allThreadsRelatedToChannelId, id, videoId

What it means

commentThreads.list requires exactly one filter: allThreadsRelatedToChannelId, id, or videoId. The controller counts non-empty values among these and throws BadRequestException when more than one is present.

Source

Thrown at project/aitoearn-electron/server/src/modules/plat/youtube/youtube.controller.ts:314

  @ApiOperation({ summary: '获取评论会话列表' })
  @Get('commentThreads/list')
  async getCommentThreadsList(
    @GetToken() token: TokenInfo,
    @Query('accountId') accountId: string,
    @Query('allThreadsRelatedToChannelId') allThreadsRelatedToChannelId: string,
    @Query('id') id: string,
    @Query('videoId') videoId: string,
    @Query('order') order?: string,
    @Query('searchTerms') searchTerms?: string,
    @Query('maxResults') maxResults?: string,
    @Query('pageToken') pageToken?: string,
    ) {
    // 校验确保只有一个参数传递
    const params = [allThreadsRelatedToChannelId, id, videoId];
    const nonEmptyParams = params.filter(param => param !== undefined && param !== null && param !== '');

    if (nonEmptyParams.length > 1) {
      throw new BadRequestException('只能选择一个参数: allThreadsRelatedToChannelId, id, videoId');
    }
    const accessToken = await this.youtubeAuthService.getUserAccessToken(accountId);
    return this.youtubeService.getCommentThreadsList(accessToken, allThreadsRelatedToChannelId, id, videoId, maxResults, pageToken, order, searchTerms);
  }

  @ApiOperation({ summary: '创建顶级评论' })
  @Post('commentThreads/insert')
  async commentThreadsInsert(
    @GetToken() token: TokenInfo,
    @Body('accountId') accountId: string,
    @Body('snippet') snippet: Record<string, any>,
  ) {
    const accessToken = await this.youtubeAuthService.getUserAccessToken(accountId);
    return this.youtubeService.insertCommentThreads(accessToken, snippet);
  }

  @ApiOperation({ summary: '获取视频类别列表' })
  @Get('video/categories/list')

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Pass exactly one of allThreadsRelatedToChannelId, id, videoId per request
  2. Reset other filter keys in client state when switching context (channel vs video vs thread)
  3. Use order/searchTerms freely — they are not part of the exclusivity rule

Example fix

// before
GET /api/plat/youtube/commentThreads/list?accountId=a&videoId=v1&allThreadsRelatedToChannelId=UC1
// after
GET /api/plat/youtube/commentThreads/list?accountId=a&videoId=v1
Defensive patterns

Strategy: validation

Validate before calling

const filters = { allThreadsRelatedToChannelId, id, videoId };
const count = Object.values(filters).filter(v => v !== undefined && v !== null && v !== '').length;
if (count > 1) throw new Error('Provide at most one of allThreadsRelatedToChannelId, id, videoId');

Try / catch

try {
  const threads = await api.get('/plat/youtube/commentThreads/list', { params });
} catch (e) {
  if (e.response?.status === 400 && String(e.response.data?.message).includes('只能选择一个参数')) {
    params = prioritizeFilter(params, ['id', 'videoId', 'allThreadsRelatedToChannelId']);
  }
}

Prevention

When it happens

Trigger: GET commentThreads/list with e.g. videoId=vid123 and allThreadsRelatedToChannelId=UCxxx together, or id plus videoId.

Common situations: UI with both a channel context and a video context sends both; cached/default query params merged with explicit filters; building the URL by concatenating optional params without resetting previous ones.

Related errors


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