yikart/AiToEarn · error · BadRequestException

userId, accountId和file是必须的

Error message

userId, accountId和file是必须的

What it means

This NestJS BadRequestException is thrown by the Twitter uploadMedia controller endpoint when the request body is missing accountId or the multipart file (userId is taken from the system token, so it fails only if the token has no id). It is a guard clause before the Twitter media upload API is called, ensuring required inputs exist. The endpoint expects a multipart/form-data upload with an 'accountId' field and a 'file' part.

Source

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

        userId: { type: 'string' },
        accountId: { type: 'string' },
        file: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @UseInterceptors(FileInterceptor('file'))
  async uploadMedia(
    @GetToken() systemToken: TokenInfo,
    // @Body('userId') userId: string,
    @Body('accountId') accountId: string,
    @UploadedFile() file: Express.Multer.File,
  ) {
    const userId = systemToken.id;
    if (!userId || !accountId || !file) {
      throw new BadRequestException('userId, accountId和file是必须的');
    }

    const accessToken = await this.twitterAuthService.getUserAccessToken(accountId);
    return this.twitterService.uploadMedia(accessToken, userId, accountId, file.buffer, file.mimetype);
  }

  /**
   * 获取推文详情
   */
  @Get('tweets/detail')
  @ApiOperation({ summary: '获取推文详情' })
  @ApiQuery({ name: 'tweetId', type: 'string', description: '推文ID' })
  // @ApiQuery({ name: 'userId', required: true, description: '用户ID' })
  @ApiQuery({ name: 'accountId', required: true, description: 'Twitter账号ID' })
  async getTweetDetail(
    @GetToken() systemToken: TokenInfo,
    @Query('tweetId') tweetId: string,
    // @Query('userId') userId: string,

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Resend the request as multipart/form-data including both an 'accountId' field and the file part named as the Multer interceptor expects.
  2. Verify the file field name in FormData matches the @UploadedFile() configuration in the controller.
  3. Check that the request carries a valid system token that resolves to a non-empty systemToken.id.
  4. Confirm the Multer file-upload interceptor (e.g. FileInterceptor) is actually applied to the route, otherwise file is always undefined.

Example fix

// before (client)
await fetch(url, { method: 'POST', body: JSON.stringify({ accountId }) });
// after (client)
const fd = new FormData();
fd.append('accountId', accountId);
fd.append('file', fileBlob, 'media.png');
await fetch(url, { method: 'POST', headers: authHeaders, body: fd });
Defensive patterns

Strategy: validation

Validate before calling

if (!accountId || !file) throw new Error('accountId和file是必须的');
// send as multipart/form-data with the file part

Type guard

function hasUploadParams(b: unknown): b is { accountId: string; file: File } {
  return typeof b === 'object' && b !== null &&
    typeof (b as any).accountId === 'string' && (b as any).accountId.length > 0 &&
    (b as any).file instanceof File;
}

Try / catch

try {
  const res = await api.post('/twitter/media/upload', fd);
} catch (e) {
  if (e.response?.status === 400 && /必须/.test(e.response.data?.message)) {
    // fix request shape: accountId + multipart file
  }
}

Prevention

When it happens

Trigger: POST to the uploadMedia endpoint with a body lacking 'accountId', or a request not sent as multipart/form-data so @UploadedFile() yields undefined, or a malformed/invalid system token whose id is falsy.

Common situations: Client sends JSON instead of multipart/form-data; file field name in FormData doesn't match the Multer interceptor's expected field; forgetting the accountId form field; calling the endpoint without a valid system token.

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/4cc90ea97036edc3. Report an issue: GitHub.