{"record":{"id":"0c6b11ab7c3caca5","repo":"yikart/AiToEarn","slug":"handle-username-id-mine","errorCode":null,"errorMessage":"只能选择一个参数: handle, userName, id 或 mine","messagePattern":"只能选择一个参数: handle, userName, id 或 mine","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"project/aitoearn-electron/server/src/modules/plat/youtube/youtube.controller.ts","lineNumber":152,"sourceCode":"  }\n\n\n  @ApiOperation({ summary: '获取频道列表' })\n  @Get('channels/list')\n  async getChannelsList(\n    @GetToken() token: TokenInfo,\n    @Query('accountId') accountId: string,\n    @Query('handle') handle?: string,\n    @Query('userName') userName?: string,\n    @Query('id') id?: string,\n    @Query('mine') mine?: boolean\n    ) {\n    // 校验确保只有一个参数传递\n    const params = [handle, userName, id, mine];\n    const nonEmptyParams = params.filter(param => param !== undefined && param !== null && param !== '');\n\n    if (nonEmptyParams.length > 1) {\n      throw new BadRequestException('只能选择一个参数: handle, userName, id 或 mine');\n    }\n    const accessToken = await this.youtubeAuthService.getUserAccessToken(accountId);\n\n    return this.youtubeService.getChannelsList(accessToken, handle, userName, id, mine);\n  }\n\n  @ApiOperation({ summary: '更新频道' })\n  @Post('channels/update')\n  async channelsUpdate(\n    @GetToken() token: TokenInfo,\n    @Body('accountId') accountId: string,\n    @Body('id') id: string,\n    @Body('brandingSettings') brandingSettings?: Record<string, any>,\n    @Body('status') status?: Record<string, any>,\n  ) {\n    const accessToken = await this.youtubeAuthService.getUserAccessToken(accountId);\n    return this.youtubeService.updateChannels(accessToken, id, brandingSettings, status);\n  }","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/plat/youtube/youtube.controller.ts#L134-L170","documentation":"YouTube Data API channel list semantics require exactly one filter selector. This controller validates that at most one of handle, userName, id, mine is provided; if more than one non-empty value is passed it throws BadRequestException '只能选择一个参数: handle, userName, id 或 mine' (choose only one parameter).","triggerScenarios":"Calling GET channels/list with e.g. both mine=true and handle=@foo, or id=UC... together with userName, in the same request.","commonSituations":"Frontend keeps previous filter state in the query string while adding a new filter; default query params (mine) sent by a client library alongside an explicit handle; copy-pasting an example URL that already includes a filter.","solutions":["Send exactly one of: handle, userName, id, or mine per request","Clear other filter params from the client state before switching filters","Decide precedence server-side if multiple are supplied instead of erroring (optional UX improvement)"],"exampleFix":"// before\nGET /api/plat/youtube/channels/list?accountId=acc1&mine=true&handle=@mychannel\n// after\nGET /api/plat/youtube/channels/list?accountId=acc1&handle=@mychannel","handlingStrategy":"validation","validationCode":"const filters = { handle, userName, id, mine };\nconst count = Object.values(filters).filter(v => v !== undefined && v !== null && v !== '').length;\nif (count > 1) throw new Error('Provide at most one of handle, userName, id, mine');\nif (count === 0) throw new Error('Provide one of handle, userName, id, mine');","typeGuard":null,"tryCatchPattern":"try {\n  const channels = await api.get('/plat/youtube/channels/list', { params: buildParams() });\n} catch (e) {\n  if (e.response?.status === 400 && String(e.response.data?.message).includes('只能选择一个参数')) {\n    params = pickSingleFilter(params); // keep highest-priority filter, retry\n  }\n}","preventionTips":["Clear previous filter values when switching selection mode in the UI","Do not send default mine=true when another filter is set","Centralize query building in one function that enforces single-filter semantics"],"tags":["http-400","validation","youtube-api","query-param"],"backgroundTag":"mutually-exclusive-parameters","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}