yikart/AiToEarn · error · BadRequestException

userId, accountId和text是必须的

Error message

userId, accountId和text是必须的

What it means

POST /plat/twitter/tweets/create publishes a tweet. userId comes from the authenticated system JWT while accountId, text, and optional mediaIds come from the JSON body. When userId, accountId, or text is missing/empty the controller throws BadRequestException('userId, accountId和text是必须的'). Note empty string '' is falsy, so blank tweet text also triggers this error.

Source

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

        // userId: { type: 'string', description: '用户ID' },
        accountId: { type: 'string', description: 'Twitter账号ID' },
        text: { type: 'string', description: '推文内容' },
        mediaIds: { type: 'array', items: { type: 'string' }, description: '媒体ID列表(可选)' }
      },
      required: ['userId', 'accountId', 'text']
    }
  })
  @HttpCode(201)
  async createTweet(
    @GetToken() systemToken: TokenInfo,
    // @Body('userId') userId: string,
    @Body('accountId') accountId: string,
    @Body('text') text: string,
    @Body('mediaIds') mediaIds?: string[],
  ) {
    const userId = systemToken.id;
    if (!userId || !accountId || !text) {
      throw new BadRequestException('userId, accountId和text是必须的');
    }

    const accessToken = await this.twitterAuthService.getUserAccessToken(accountId);
    return this.twitterService.createTweet(accessToken, userId, accountId, text, mediaIds);
  }

  /**
   * 上传媒体文件
   */
  @Post('media/upload')
  @ApiOperation({ summary: '上传媒体文件' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'string' },
        accountId: { type: 'string' },

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Ensure the request carries a valid JWT and JSON body {"accountId":"...","text":"..."} with Content-Type: application/json
  2. Validate text is a non-empty string client-side before calling (trim and length-check)
  3. If attaching media, upload first via POST /plat/twitter/media/upload then pass mediaIds along with text
  4. Re-login if the JWT expired so userId resolves

Example fix

// before
await api.post('/plat/twitter/tweets/create', { accountId, text: content.trim() ? content : undefined });
// after
if (!content.trim()) throw new Error('Tweet text is required');
await api.post('/plat/twitter/tweets/create', { accountId, text: content, mediaIds }, { headers: { 'Content-Type': 'application/json' } });
Defensive patterns

Strategy: validation

Validate before calling

const text = (content ?? '').trim();
if (!systemToken || !accountId || !text) {
  throw new Error('Tweet requires an authenticated user, accountId and non-empty text');
}
await api.post('/plat/twitter/tweets/create', { accountId, text, mediaIds });

Type guard

function isCreateTweetBody(b: unknown): b is { accountId: string; text: string; mediaIds?: string[] } {
  const x = b as any;
  return !!x && typeof x.accountId === 'string' && x.accountId.length > 0
    && typeof x.text === 'string' && x.text.trim().length > 0
    && (x.mediaIds === undefined || (Array.isArray(x.mediaIds) && x.mediaIds.every(i => typeof i === 'string')));
}

Try / catch

try {
  return await api.post('/plat/twitter/tweets/create', body);
} catch (e) {
  if (e.response?.status === 400) {
    console.error('createTweet rejected: ensure valid JWT and a JSON body with accountId and non-empty text');
  }
  throw e;
}

Prevention

When it happens

Trigger: Unauthenticated/expired request (no systemToken.id); body missing accountId or text; text sent as empty string; body not sent as JSON so @Body() fields are all undefined; calling with mediaIds-only content and no text.

Common situations: Composer UI allowing an empty post; file uploads not accepted by the text-only endpoint (use /media/upload separately); automation scripts with malformed JSON or missing Content-Type: application/json; expired session JWT.

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