{"record":{"id":"112b0f8651d3eb68","repo":"yikart/AiToEarn","slug":"accountid-112b0f","errorCode":null,"errorMessage":"accountId是必须的","messagePattern":"accountId是必须的","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-electron/server/src/modules/plat/twitter/twitter.controller.ts","lineNumber":93,"sourceCode":"\n      // 重定向到前端失败页面，带上错误信息\n      // return res.redirect(`${failureRedirectUrl}?error=${encodeURIComponent(error.message || 'Unknown error')}`);\n      return false\n    }\n  }\n\n  /**\n   * 检查用户是否已授权Twitter\n   */\n  @Get('auth/check')\n  @ApiOperation({ summary: '检查用户Twitter授权状态' })\n  @ApiQuery({ name: 'accountId', required: true, description: 'Twitter账号ID' })\n  async checkAuthStatus(\n    @GetToken() systemToken: TokenInfo,\n    @Query('accountId') accountId: string\n    ) {\n    if (!accountId) {\n      throw new BadRequestException('accountId是必须的');\n    }\n\n    return await this.twitterAuthService.isAuthorized(accountId);\n  }\n\n  /**\n   * 撤销Twitter授权\n   */\n  @Post('auth/revoke')\n  @ApiOperation({ summary: '撤销Twitter授权' })\n  @ApiBody({\n    schema: {\n      type: 'object',\n      properties: {\n        accountId: { type: 'string', description: 'Twitter账号ID' }\n      }\n    }\n  })","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/plat/twitter/twitter.controller.ts#L75-L111","documentation":"GET /plat/twitter/auth/check verifies whether a Twitter account is authorized. It requires the accountId query parameter; when absent the controller throws BadRequestException('accountId是必须的') (HTTP 400). Note systemToken is injected but the accountId is not ownership-checked here — only its presence is validated.","triggerScenarios":"Calling GET /plat/twitter/auth/check without ?accountId=... or with accountId= (empty string); client building the request dynamically with an undefined account variable that serializes to nothing.","commonSituations":"Frontend state not yet loaded when the check fires (account list still empty); Swagger/manual calls omitting the query; template literals like `?accountId=${undefined}` in fetch helpers dropping the param.","solutions":["Always append accountId: GET /plat/twitter/auth/check?accountId=<id>","Guard client-side: only call once the account id is loaded, e.g. if (!accountId) return;","Trim the id — whitespace-only strings pass URL building but a truly empty value triggers the 400","If accountId comes from a route param or store, verify the fetch happens after that store hydrates"],"exampleFix":"// before\nuseEffect(() => { checkAuth(accountId); }, []); // accountId may be undefined\n// after\nuseEffect(() => { if (accountId) checkAuth(accountId); }, [accountId]);","handlingStrategy":"validation","validationCode":"if (typeof accountId !== 'string' || !accountId.trim()) {\n  throw new Error('accountId is required before checking auth status');\n}\nawait api.get('/plat/twitter/auth/check', { params: { accountId } });","typeGuard":"function isNonEmptyString(v: unknown): v is string {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  return await api.get('/plat/twitter/auth/check', { params: { accountId } });\n} catch (e) {\n  if (e.response?.status === 400) return false; // treat as not-authorized rather than crashing the UI\n  throw e;\n}","preventionTips":["Gate the call on accountId being loaded from your account store","Use the required:true Swagger query contract — omitting it always 400s","Debounce checks so they don't fire with stale/empty state on mount","Normalize ids (trim) before sending"],"tags":["validation","bad-request","query-params"],"backgroundTag":"missing-required-parameter","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}