yikart/AiToEarn · error · BadRequestException

Only one last frame image is allowed

Error message

Only one last frame image is allowed

What it means

Same constraint as first frame: Volcengine accepts at most one last frame image. validateContent throws this BadRequestException when more than one image content item with the last-frame role is present.

Source

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

    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')
    }

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

    if (lastFrameImages.length > 0 && firstFrameImages.length === 0) {
      throw new BadRequestException('last_frame requires first_frame')
    }

    if (hasFrameScene && hasReferenceScene) {
      throw new BadRequestException('first_frame/last_frame and reference media cannot be mixed')
    }

    if (referenceAudios.length > 0 && referenceImages.length === 0 && referenceVideos.length === 0) {
      throw new BadRequestException('reference_audio requires at least one reference image or reference video')
    }
  }

  private normalizeRequest(request: UserVolcengineGenerationRequestDto) {
    let prompt = ''
    let inlineResolution: string | undefined

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Keep exactly one last-frame image content item
  2. Drop or re-role the extra last-frame images
  3. Validate last-frame count client-side before calling

Example fix

// before
content: [lastA, lastB].map(u => ({ type:'image_url', role:'last_frame', url: u }))
// after
content: [{ type:'image_url', role:'last_frame', url: lastA }]
Defensive patterns

Strategy: validation

Validate before calling

const lastFrames = content.filter(c => c.type === 'image_url' && c.role === 'last_frame'); if (lastFrames.length > 1) throw new Error('Only one last frame image is allowed')

Type guard

const isSingleLastFrame = (c: Content[]) => c.filter(i => i.type === ContentType.ImageUrl && i.role === 'last_frame').length <= 1

Try / catch

try { await generate(req) } catch (e) { if (e instanceof BadRequestException && e.message.includes('last frame image')) { /* keep only one last-frame image and retry */ } else throw e }

Prevention

When it happens

Trigger: Supplying 2+ ImageUrl content items with the last-frame role in a generation request.

Common situations: UI allowing multiple end frames; loops appending every uploaded image as last_frame; schema changes where an array of end frames was previously allowed.

Related errors


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