{"record":{"id":"a6c1a7399a8d4bc1","repo":"yikart/AiToEarn","slug":"channelid-playlistids-mine","errorCode":null,"errorMessage":"只能选择一个参数: channelId, playListIds, mine","messagePattern":"只能选择一个参数: channelId, playListIds, mine","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"project/aitoearn-electron/server/src/modules/plat/youtube/youtube.controller.ts","lineNumber":442,"sourceCode":"  }\n\n  @ApiOperation({ summary: '获取播放列表' })\n  @Get('playlist/list')\n  async getPlayList(\n    @GetToken() token: TokenInfo,\n    @Query('accountId') accountId: string,\n    @Query('channelId') channelId?: string,\n    @Query('id') playListIds?: string,\n    @Query('mine') mine?: boolean,\n    @Query('maxResults') maxResults?: string,\n    @Query('pageToken') pageToken?: string,\n    ) {\n    // 校验确保只有一个参数传递\n    const params = [channelId, playListIds, mine];\n    const nonEmptyParams = params.filter(param => param !== undefined && param !== null && param !== '');\n\n    if (nonEmptyParams.length > 1) {\n      throw new BadRequestException('只能选择一个参数: channelId, playListIds, mine');\n    }\n    const accessToken = await this.youtubeAuthService.getUserAccessToken(accountId);\n    return this.youtubeService.getPlayList(accessToken, channelId, playListIds, mine, maxResults, pageToken);\n  }\n\n  @ApiOperation({ summary: '更新播放列表' })\n  @Post('playlist/update')\n  async playlistUpdate(\n    @GetToken() token: TokenInfo,\n    @Body('accountId') accountId: string,\n    @Body('playListId') playListId: string,\n    @Body('snippet') snippet?: Record<string, any>,\n    @Body('status') status?: Record<string, any>,\n  ) {\n    const accessToken = await this.youtubeAuthService.getUserAccessToken(accountId);\n    return this.youtubeService.updatePlayList(accessToken, playListId, snippet, status);\n  }\n","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/plat/youtube/youtube.controller.ts#L424-L460","documentation":"The getPlayList endpoint accepts three mutually-exclusive modes: `channelId` (lists a channel's playlists), `playListIds` (fetch specific playlists), or `mine=true` (list the authenticated user's playlists). The controller counts non-empty params and throws BadRequestException if more than one is supplied, mirroring how the YouTube Data API requires a single filter. This is thrown before the Google API call.","triggerScenarios":"Calling the playlists endpoint with e.g. ?channelId=UC...&mine=true, or ?playListIds=PL1&mine=true — any combination of two or three of channelId/playListIds/mine that are non-empty (undefined/null/'' filtered out).","commonSituations":"Clients defaulting `mine` to a truthy value while also passing a channelId; bulk fetch code appending both playListIds and a channel filter; copy-pasted curl commands retaining params from a previous example.","solutions":["Pass exactly one of channelId, playListIds, mine per request; remove the others.","Add client-side logic that clears the other fields when one mode is selected.","Split needs into multiple calls (one per mode) and merge results in the client.","Check the request URL/interceptor logs for stale default params like mine=true."],"exampleFix":"// before\nclient.getPlayList(accountId, channelId, playListIds, true);\n// after\nclient.getPlayList(accountId, playListIds ? undefined : channelId, playListIds, playListIds ? undefined : true);","handlingStrategy":"validation","validationCode":"const modes = [channelId, playListIds, mine].filter(v => v !== undefined && v !== null && v !== '');\nif (modes.length !== 1) throw new Error('Exactly one of channelId, playListIds, mine must be set');","typeGuard":"type PlaylistQuery = { channelId?: string } | { playListIds?: string[] } | { mine?: boolean };\nfunction isSingleModeQuery(q: PlaylistQuery): boolean {\n  return Object.values(q).filter(v => v !== undefined && v !== null && v !== '').length === 1;\n}","tryCatchPattern":"try {\n  return await client.getPlayList(accountId, undefined, undefined, true);\n} catch (e) {\n  if (String(e.message).includes('只能选择一个参数')) console.error('Playlist query mixed modes; fix caller');\n  throw e;\n}","preventionTips":["Model the request as a discriminated union so only one mode is expressible.","Clear sibling fields when one mode is selected in UI.","Intercept and inspect outgoing URLs in dev to catch stale defaults like mine=true.","Write a unit test asserting the param-builder emits exactly one mode."],"tags":["bad-request","input-validation","youtube-api","mutually-exclusive-params"],"backgroundTag":"mutually-exclusive-params","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}