yikart/AiToEarn · error · BadRequestException

content is required

Error message

content is required

What it means

validateContent in volcengine.service.ts throws this BadRequestException when the content array of a Volcengine video generation request is empty. The Volcengine API requires at least one content item (text or media) to build a generation request, so normalizeRequest rejects the request before it reaches the provider.

Source

Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/volcengine/volcengine.service.ts:146

  private buildSafetyIdentifier(userId: string, userType: UserType): string {
    return `${userType}:${userId}`
  }

  private getFailureMessage(status: VolcTaskStatus, callbackData: VolcengineCallbackDto): string | undefined {
    if (status === VolcTaskStatus.Failed) {
      return callbackData.error?.message || 'Volcengine task failed'
    }

    if (status === VolcTaskStatus.Expired) {
      return callbackData.error?.message || 'Volcengine task expired'
    }

    return undefined
  }

  private validateContent(content: Content[]) {
    if (content.length === 0) {
      throw new BadRequestException('content is required')
    }

    const imageContents = content.filter((item): item is Extract<Content, { type: ContentType.ImageUrl }> => item.type === ContentType.ImageUrl)
    const videoContents = content.filter((item): item is Extract<Content, { type: ContentType.VideoUrl }> => item.type === ContentType.VideoUrl)
    const audioContents = content.filter((item): item is Extract<Content, { type: ContentType.AudioUrl }> => item.type === ContentType.AudioUrl)

    const firstFrameImages = imageContents.filter(item => !item.role || item.role === ImageRole.FirstFrame)
    const lastFrameImages = imageContents.filter(item => item.role === ImageRole.LastFrame)
    const referenceImages = imageContents.filter(item => item.role === ImageRole.ReferenceImage)
    const referenceVideos = videoContents.filter(item => item.role === VideoRole.ReferenceVideo)
    const referenceAudios = audioContents.filter(item => item.role === AudioRole.ReferenceAudio)

    const hasFrameScene = firstFrameImages.length > 0 || lastFrameImages.length > 0
    const hasReferenceScene = referenceImages.length > 0 || referenceVideos.length > 0 || referenceAudios.length > 0

    if (firstFrameImages.length > 1) {
      throw new BadRequestException('Only one first frame image is allowed')
    }

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Add at least one content item (a text prompt or an image/video/audio URL) to the request
  2. Check the client code that builds the content array — ensure it pushes items before sending
  3. Validate content.length > 0 on the client before calling the API

Example fix

// before
await api.generate({ model: 'doubao-seedance', content: [] })
// after
await api.generate({ model: 'doubao-seedance', content: [{ type: 'text', text: 'a cat running' }] })
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(content) || content.length === 0) throw new Error('content is required: add at least one text or media content item')

Type guard

const hasContent = (c: unknown): c is Content[] => Array.isArray(c) && c.length > 0

Try / catch

try { await generate(req) } catch (e) { if (e instanceof BadRequestException && e.message === 'content is required') { /* prompt user to add content */ } else throw e }

Prevention

When it happens

Trigger: Calling the Volcengine video generation endpoint with content: [] or omitting all content items in UserVolcengineGenerationRequestDto.

Common situations: Clients sending only optional fields (return_last_frame, resolution) without prompt or media; frontend forms that allow submitting with no image and empty prompt; broken serialization dropping content.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/4023b1760cd882d4. Report an issue: GitHub.